home *** CD-ROM | disk | FTP | other *** search
/ Micromanía 92 / CDMM92_1.ISO / SOF 2 SDK / sof2sdk-101.msi / _92D6AC311BB48EBA344BBABC89DA6AB0 / _BD38A71AAE9747B4BBA24C8F89356576 < prev    next >
Encoding:
Text File  |  2002-07-01  |  86.2 KB  |  3,998 lines

  1. // Copyright (C) 2001-2002 Raven Software
  2. //
  3. // bg_pmove.c -- both games player movement code
  4. // takes a playerstate and a usercmd as input and returns a modifed playerstate
  5.  
  6. #include "q_shared.h"
  7. #include "bg_public.h"
  8. #include "bg_local.h"
  9.  
  10. pmove_t        *pm;
  11. pml_t        pml;
  12.  
  13. // Speed scales
  14. float        pm_stopspeed            = 100.0f;
  15. float        pm_duckScale            = 0.25f;
  16. float        pm_swimScale            = 0.50f;
  17. float        pm_wadeScale            = 0.70f;
  18. const float    pm_ladderScale            = 0.5f;
  19.                 
  20. // Accelerations
  21. float        pm_accelerate            = 6.0f;
  22. float        pm_airaccelerate        = 1.0f;
  23. float        pm_wateraccelerate        = 4.0f;
  24. float        pm_flyaccelerate        = 8.0f;
  25.                                     
  26. // Frictions                            
  27. float        pm_headfriction            = 0.0f;            // Friction when on someones head
  28. float        pm_friction                = 6.0f;            // Friction when on the ground
  29. float        pm_waterfriction        = 3.0f;            // Friction when in water
  30. float        pm_ladderfriction        = 6.0f;            // Friction when on a ladder
  31. float        pm_spectatorfriction    = 5.0f;            // Friction when flying aroudn as a spectator
  32.  
  33. int            c_pmove = 0;
  34.  
  35. ladder_t    pm_ladders[MAX_LADDERS];
  36. int            pm_laddercount = 0;
  37.  
  38. static void PM_Weapon_AddInaccuracy    ( attackType_t attack );
  39. static void PM_Weapon_AddKickAngles    ( vec3_t kickAngles );
  40. static void PM_BeginZoomOut            ( void );
  41.  
  42. /*
  43. ===============
  44. PM_AddEvent
  45. ===============
  46. */
  47. void PM_AddEvent( int newEvent ) 
  48. {
  49.     BG_AddPredictableEventToPlayerstate( newEvent, 0, pm->ps );
  50. }
  51.  
  52. /*
  53. ===============
  54. PM_AddEventWithParm
  55. ===============
  56. */
  57. void PM_AddEventWithParm( int newEvent, int parm ) 
  58. {
  59.     BG_AddPredictableEventToPlayerstate( newEvent, parm, pm->ps );
  60. }
  61.  
  62. /*
  63. ===============
  64. PM_AddTouchEnt
  65. ===============
  66. */
  67. void PM_AddTouchEnt ( int entityNum ) 
  68. {
  69.     int        i;
  70.  
  71.     // Cant add the world as a touch entity
  72.     if ( entityNum == ENTITYNUM_WORLD ) 
  73.     {
  74.         return;
  75.     }
  76.  
  77.     // Ensure the max touch limit has not been reached
  78.     if ( pm->numtouch == MAXTOUCH ) 
  79.     {
  80.         return;
  81.     }
  82.  
  83.     // see if it is already added
  84.     for ( i = 0 ; i < pm->numtouch ; i++ ) 
  85.     {
  86.         if ( pm->touchents[ i ] == entityNum ) 
  87.         {
  88.             return;
  89.         }
  90.     }
  91.  
  92.     // add it
  93.     pm->touchents[pm->numtouch] = entityNum;
  94.     pm->numtouch++;
  95. }
  96.  
  97.  
  98. /*
  99. ==================
  100. PM_ClipVelocity
  101.  
  102. Slide off of the impacting surface
  103. ==================
  104. */
  105. void PM_ClipVelocity( vec3_t in, vec3_t normal, vec3_t out, float overbounce ) 
  106. {
  107.     float    backoff;
  108.     float    change;
  109.     int        i;
  110.     
  111.     backoff = DotProduct (in, normal);
  112.     
  113.     if ( backoff < 0 ) 
  114.     {
  115.         backoff *= overbounce;
  116.     } 
  117.     else 
  118.     {
  119.         backoff /= overbounce;
  120.     }
  121.  
  122.     for ( i=0 ; i<3 ; i++ ) 
  123.     {
  124.         change = normal[i]*backoff;
  125.         out[i] = in[i] - change;
  126.     }
  127. }
  128.  
  129.  
  130. /*
  131. ==================
  132. PM_Friction
  133.  
  134. Handles both ground friction and water friction
  135. ==================
  136. */
  137. static void PM_Friction( void ) 
  138. {
  139.     vec3_t    vec;
  140.     float    *vel;
  141.     float    speed, newspeed, control;
  142.     float    drop;
  143.     
  144.     vel = pm->ps->velocity;
  145.     
  146.     VectorCopy( vel, vec );
  147.     if ( pml.walking ) 
  148.     {
  149.         vec[2] = 0;    // ignore slope movement
  150.     }
  151.  
  152.     speed = VectorLength(vec);
  153.     if (speed < 1) 
  154.     {
  155.         vel[0] = 0;
  156.         vel[1] = 0;        // allow sinking underwater
  157.         // FIXME: still have z friction underwater?
  158.         return;
  159.     }
  160.  
  161.     drop = 0;
  162.  
  163.     // apply ground friction
  164.     if ( pm->waterlevel <= 1 ) 
  165.     {
  166.         if ( pml.walking && !(pml.groundTrace.surfaceFlags & SURF_SLICK) ) 
  167.         {
  168.             // if getting knocked back, no friction
  169.             if ( ! (pm->ps->pm_flags & PMF_TIME_KNOCKBACK) ) 
  170.             {
  171.                 control = speed < pm_stopspeed ? pm_stopspeed : speed;
  172.                 drop += control*pm_friction*pml.frametime;
  173.             }
  174.         }
  175.     }
  176.  
  177.     // apply water friction even if just wading
  178.     if ( pm->ps->pm_flags & PMF_LADDER )  
  179.     {
  180.         if ( !pml.groundPlane )
  181.         {
  182.             control = speed < pm_stopspeed ? pm_stopspeed : speed;
  183.             drop += control*pm_ladderfriction*pml.frametime;
  184.         }
  185.     }
  186.     else if ( pm->waterlevel > 1 ) 
  187.     {
  188.         drop += speed*pm_waterfriction*pm->waterlevel*pml.frametime;
  189.     }
  190.     // If on someones head then use special friction
  191.     else if ( pm->ps->groundEntityNum < MAX_CLIENTS )
  192.     {
  193.         drop = speed*pm_headfriction*pml.frametime;
  194.     }
  195.  
  196.     if ( pm->ps->pm_type == PM_SPECTATOR) 
  197.     {
  198.         drop += speed*pm_spectatorfriction*pml.frametime;
  199.     }
  200.  
  201.  
  202.     // scale the velocity
  203.     newspeed = speed - drop;
  204.     if (newspeed < 0) 
  205.     {
  206.         newspeed = 0;
  207.     }
  208.     newspeed /= speed;
  209.  
  210.     vel[0] = vel[0] * newspeed;
  211.     vel[1] = vel[1] * newspeed;
  212.     vel[2] = vel[2] * newspeed;
  213. }
  214.  
  215.  
  216. /*
  217. ==============
  218. PM_Accelerate
  219.  
  220. Handles user intended acceleration
  221. ==============
  222. */
  223. static void PM_Accelerate( vec3_t wishdir, float wishspeed, float accel ) 
  224. {
  225. #if 1
  226.     // q2 style
  227.     int            i;
  228.     float        addspeed, accelspeed, currentspeed;
  229.  
  230.     currentspeed = DotProduct (pm->ps->velocity, wishdir);
  231.     addspeed = wishspeed - currentspeed;
  232.     if (addspeed <= 0) {
  233.         return;
  234.     }
  235.     accelspeed = accel*pml.frametime*wishspeed;
  236.     if (accelspeed > addspeed) {
  237.         accelspeed = addspeed;
  238.     }
  239.     
  240.     for (i=0 ; i<3 ; i++) {
  241.         pm->ps->velocity[i] += accelspeed*wishdir[i];    
  242.     }
  243. #else
  244.     // proper way (avoids strafe jump maxspeed bug), but feels bad
  245.     vec3_t        wishVelocity;
  246.     vec3_t        pushDir;
  247.     float        pushLen;
  248.     float        canPush;
  249.  
  250.     VectorScale( wishdir, wishspeed, wishVelocity );
  251.     VectorSubtract( wishVelocity, pm->ps->velocity, pushDir );
  252.     pushLen = VectorNormalize( pushDir );
  253.  
  254.     canPush = accel*pml.frametime*wishspeed;
  255.     if (canPush > pushLen) {
  256.         canPush = pushLen;
  257.     }
  258.  
  259.     VectorMA( pm->ps->velocity, canPush, pushDir, pm->ps->velocity );
  260. #endif
  261. }
  262.  
  263. /*
  264. ============
  265. PM_CmdScale
  266.  
  267. Returns the scale factor to apply to cmd movements
  268. This allows the clients to use axial -127 to 127 values for all directions
  269. without getting a sqrt(2) distortion in speed.
  270. ============
  271. */
  272. static float PM_CmdScale( usercmd_t *cmd ) 
  273. {
  274.     int        max;
  275.     float    total;
  276.     float    scale;
  277.  
  278.     max = abs( cmd->forwardmove );
  279.     if ( abs( cmd->rightmove ) > max ) 
  280.     {
  281.         max = abs( cmd->rightmove );
  282.     }
  283.     
  284.     if ( abs( cmd->upmove ) > max ) 
  285.     {
  286.         max = abs( cmd->upmove );
  287.     }
  288.  
  289.     if ( !max ) 
  290.     {
  291.         return 0;
  292.     }
  293.  
  294.     total = sqrt( cmd->forwardmove * cmd->forwardmove
  295.         + cmd->rightmove * cmd->rightmove + cmd->upmove * cmd->upmove );
  296.     scale = (float)pm->ps->speed * max / ( 127.0 * total );
  297.  
  298.     return scale;
  299. }
  300.  
  301.  
  302. /*
  303. ================
  304. PM_SetMovementDir
  305.  
  306. Determine the rotation of the legs reletive
  307. to the facing dir
  308. ================
  309. */
  310. static void PM_SetMovementDir( void ) 
  311. {
  312.     if ( pm->cmd.forwardmove || pm->cmd.rightmove ) 
  313.     {
  314.         if ( pm->cmd.rightmove == 0 && pm->cmd.forwardmove > 0 ) 
  315.         {
  316.             pm->ps->movementDir = 0;
  317.         } 
  318.         else if ( pm->cmd.rightmove < 0 && pm->cmd.forwardmove > 0 ) 
  319.         {
  320.             pm->ps->movementDir = 1;
  321.         } 
  322.         else if ( pm->cmd.rightmove < 0 && pm->cmd.forwardmove == 0 ) 
  323.         {
  324.             pm->ps->movementDir = 2;
  325.         } 
  326.         else if ( pm->cmd.rightmove < 0 && pm->cmd.forwardmove < 0 ) 
  327.         {
  328.             pm->ps->movementDir = 3;
  329.         } 
  330.         else if ( pm->cmd.rightmove == 0 && pm->cmd.forwardmove < 0 ) 
  331.         {
  332.             pm->ps->movementDir = 4;
  333.         }
  334.         else if ( pm->cmd.rightmove > 0 && pm->cmd.forwardmove < 0 ) 
  335.         {
  336.             pm->ps->movementDir = 5;
  337.         } 
  338.         else if ( pm->cmd.rightmove > 0 && pm->cmd.forwardmove == 0 ) 
  339.         {
  340.             pm->ps->movementDir = 6;
  341.         } 
  342.         else if ( pm->cmd.rightmove > 0 && pm->cmd.forwardmove > 0 ) 
  343.         {
  344.             pm->ps->movementDir = 7;
  345.         }
  346.     } 
  347.     else 
  348.     {
  349.         // if they aren't actively going directly sideways,
  350.         // change the animation to the diagonal so they
  351.         // don't stop too crooked
  352.         if ( pm->ps->movementDir == 2 ) 
  353.         {
  354.             pm->ps->movementDir = 1;
  355.         } 
  356.         else if ( pm->ps->movementDir == 6 ) 
  357.         {
  358.             pm->ps->movementDir = 7;
  359.         } 
  360.     }
  361. }
  362.  
  363. /*
  364. =============
  365. PM_CheckJump
  366. =============
  367. */
  368. static qboolean PM_CheckJump( void ) 
  369. {
  370.     if ( pm->ps->pm_time )
  371.     {
  372.         return qfalse;
  373.     }
  374.  
  375.     // Cant jump when ducked
  376.     if ( pm->ps->pm_flags & PMF_DUCKED ) 
  377.     {
  378.         return qfalse;
  379.     }
  380.  
  381.     // don't allow jump until all buttons are up
  382.     if ( pm->ps->pm_flags & PMF_RESPAWNED ) 
  383.     {
  384.         return qfalse;        
  385.     }
  386.  
  387.     // not holding jump
  388.     if ( pm->cmd.upmove < 10 ) 
  389.     {
  390.         return qfalse;
  391.     }
  392.  
  393.     // must wait for jump to be released
  394.     if ( pm->ps->pm_debounce & PMD_JUMP )
  395.     {
  396.         // clear upmove so cmdscale doesn't lower running speed
  397.         pm->cmd.upmove = 0;
  398.         return qfalse;
  399.     }
  400.  
  401.     pml.groundPlane = qfalse;        // jumping away
  402.     pml.walking = qfalse;
  403.     pm->ps->pm_debounce |= PMD_JUMP;
  404.     pm->ps->pm_flags |= PMF_JUMPING;
  405.  
  406.     pm->ps->groundEntityNum = ENTITYNUM_NONE;
  407.  
  408.     if ( pm->cmd.forwardmove >= 0 ) 
  409.     {
  410.         PM_ForceLegsAnim( pm->ps, LEGS_JUMP );
  411.     } 
  412.     else 
  413.     {
  414.         PM_ForceLegsAnim( pm->ps, LEGS_JUMP_BACK );
  415.         pm->ps->pm_flags |= PMF_BACKWARDS_JUMP;
  416.     }
  417.  
  418.     // Special case for ladders
  419.     if ( pm->ps->ladder != -1 )
  420.     {
  421.         vec3_t forward;    
  422.         VectorCopy ( pm_ladders[pm->ps->ladder].fwd, forward );
  423.         forward[2] = 0;
  424.         VectorNormalize ( forward );
  425.         VectorMA ( pm->ps->velocity, -50, forward, pm->ps->velocity );
  426.         pm->ps->pm_flags |= PMF_LADDER_JUMP;
  427.         return qtrue;
  428.     }
  429.  
  430.     pm->ps->velocity[2] = JUMP_VELOCITY;
  431.  
  432.     return qtrue;
  433. }
  434.  
  435. /*
  436. =============
  437. PM_CheckWaterJump
  438. =============
  439. */
  440. static qboolean    PM_CheckWaterJump( void ) 
  441. {
  442.     vec3_t    spot;
  443.     int        cont;
  444.     vec3_t    flatforward;
  445.  
  446.     if (pm->ps->pm_time) 
  447.     {
  448.         return qfalse;
  449.     }
  450.  
  451.     // check for water jump
  452.     if ( pm->waterlevel != 2 ) 
  453.     {
  454.         return qfalse;
  455.     }
  456.  
  457.     flatforward[0] = pml.forward[0];
  458.     flatforward[1] = pml.forward[1];
  459.     flatforward[2] = 0;
  460.     VectorNormalize (flatforward);
  461.  
  462.     VectorMA (pm->ps->origin, 30, flatforward, spot);
  463.     spot[2] += 4;
  464.     cont = pm->pointcontents (spot, pm->ps->clientNum );
  465.     if ( !(cont & CONTENTS_SOLID) ) 
  466.     {
  467.         return qfalse;
  468.     }
  469.  
  470.     spot[2] += 16;
  471.     cont = pm->pointcontents (spot, pm->ps->clientNum );
  472.     if ( cont ) 
  473.     {
  474.         return qfalse;
  475.     }
  476.  
  477.     // jump out of water
  478.     VectorScale (pml.forward, 200, pm->ps->velocity);
  479.     pm->ps->velocity[2] = 350;
  480.  
  481.     pm->ps->pm_flags |= PMF_TIME_WATERJUMP;
  482.     pm->ps->pm_time = 2000;
  483.  
  484.     return qtrue;
  485. }
  486.  
  487. /*
  488. ===================
  489. PM_WaterJumpMove
  490.  
  491. Flying out of the water
  492. ===================
  493. */
  494. static void PM_WaterJumpMove( void ) 
  495. {
  496.     // waterjump has no control, but falls
  497.     PM_StepSlideMove( qtrue );
  498.  
  499.     pm->ps->velocity[2] -= pm->ps->gravity * pml.frametime;
  500.     if (pm->ps->velocity[2] < 0) 
  501.     {
  502.         // cancel as soon as we are falling down again
  503.         pm->ps->pm_flags &= ~PMF_ALL_TIMES;
  504.         pm->ps->pm_time = 0;
  505.     }
  506. }
  507.  
  508. /*
  509. ===================
  510. PM_WaterMove
  511. ===================
  512. */
  513. static void PM_WaterMove( void ) 
  514. {
  515.     int        i;
  516.     vec3_t    wishvel;
  517.     float    wishspeed;
  518.     vec3_t    wishdir;
  519.     float    scale;
  520.     float    vel;
  521.  
  522.     if ( PM_CheckWaterJump() ) 
  523.     {
  524.         PM_WaterJumpMove();
  525.         return;
  526.     }
  527.  
  528. #if 0
  529.     // jump = head for surface
  530.     if ( pm->cmd.upmove >= 10 ) {
  531.         if (pm->ps->velocity[2] > -300) {
  532.             if ( pm->watertype == CONTENTS_WATER ) {
  533.                 pm->ps->velocity[2] = 100;
  534.             } else {
  535.                 pm->ps->velocity[2] = 50;
  536.             }
  537.         }
  538.     }
  539. #endif
  540.     PM_Friction ();
  541.  
  542.     scale = PM_CmdScale( &pm->cmd );
  543.     //
  544.     // user intentions
  545.     //
  546.     if ( !scale ) 
  547.     {
  548.         wishvel[0] = 0;
  549.         wishvel[1] = 0;
  550.         wishvel[2] = -60;        // sink towards bottom
  551.     } 
  552.     else 
  553.     {
  554.         for (i=0 ; i<3 ; i++)
  555.         {
  556.             wishvel[i] = scale * pml.forward[i]*pm->cmd.forwardmove + scale * pml.right[i]*pm->cmd.rightmove;
  557.         }
  558.  
  559.         wishvel[2] += scale * pm->cmd.upmove;
  560.     }
  561.  
  562.     VectorCopy (wishvel, wishdir);
  563.     wishspeed = VectorNormalize(wishdir);
  564.  
  565.     if ( wishspeed > pm->ps->speed * pm_swimScale ) 
  566.     {
  567.         wishspeed = pm->ps->speed * pm_swimScale;
  568.     }
  569.  
  570.     PM_Accelerate (wishdir, wishspeed, pm_wateraccelerate);
  571.  
  572.     // make sure we can go up slopes easily under water
  573.     if ( pml.groundPlane && DotProduct( pm->ps->velocity, pml.groundTrace.plane.normal ) < 0 ) 
  574.     {
  575.         vel = VectorLength(pm->ps->velocity);
  576.         // slide along the ground plane
  577.         PM_ClipVelocity (pm->ps->velocity, pml.groundTrace.plane.normal, 
  578.             pm->ps->velocity, OVERCLIP );
  579.  
  580.         VectorNormalize(pm->ps->velocity);
  581.         VectorScale(pm->ps->velocity, vel, pm->ps->velocity);
  582.     }
  583.  
  584.     PM_SlideMove( qfalse );
  585. }
  586.  
  587. /*
  588. ===================
  589. PM_FlyMove
  590. ===================
  591. */
  592. static void PM_FlyMove( void ) 
  593. {
  594.     int        i;
  595.     vec3_t    wishvel;
  596.     float    wishspeed;
  597.     vec3_t    wishdir;
  598.     float    scale;
  599.  
  600.     // normal slowdown
  601.     PM_Friction ();
  602.  
  603.     scale = PM_CmdScale( &pm->cmd );
  604.     //
  605.     // user intentions
  606.     //
  607.     if ( !scale ) 
  608.     {
  609.         wishvel[0] = 0;
  610.         wishvel[1] = 0;
  611.         wishvel[2] = 0;
  612.     } 
  613.     else 
  614.     {
  615.         for (i=0 ; i<3 ; i++) 
  616.         {
  617.             wishvel[i] = scale * pml.forward[i]*pm->cmd.forwardmove + scale * pml.right[i]*pm->cmd.rightmove;
  618.         }
  619.  
  620.         wishvel[2] += scale * pm->cmd.upmove;
  621.     }
  622.  
  623.     VectorCopy (wishvel, wishdir);
  624.     wishspeed = VectorNormalize(wishdir);
  625.  
  626.     PM_Accelerate (wishdir, wishspeed, pm_flyaccelerate);
  627.  
  628.     PM_StepSlideMove( qfalse );
  629. }
  630.  
  631.  
  632. /*
  633. ===================
  634. PM_AirMove
  635.  
  636. ===================
  637. */
  638. static void PM_AirMove( void ) 
  639. {
  640.     int            i;
  641.     vec3_t        wishvel;
  642.     float        fmove, smove;
  643.     vec3_t        wishdir;
  644.     float        wishspeed;
  645.     float        scale;
  646.     usercmd_t    cmd;
  647.  
  648.     PM_Friction();
  649.  
  650.     fmove = pm->cmd.forwardmove;
  651.     smove = pm->cmd.rightmove;
  652.  
  653.     cmd = pm->cmd;
  654.     scale = PM_CmdScale( &cmd );
  655.  
  656.     // set the movementDir so clients can rotate the legs for strafing
  657.     PM_SetMovementDir();
  658.  
  659.     // project moves down to flat plane
  660.     pml.forward[2] = 0;
  661.     pml.right[2] = 0;
  662.     VectorNormalize (pml.forward);
  663.     VectorNormalize (pml.right);
  664.  
  665.     for ( i = 0 ; i < 2 ; i++ ) {
  666.         wishvel[i] = pml.forward[i]*fmove + pml.right[i]*smove;
  667.     }
  668.     wishvel[2] = 0;
  669.  
  670.     VectorCopy (wishvel, wishdir);
  671.     wishspeed = VectorNormalize(wishdir);
  672.     wishspeed *= scale;
  673.  
  674.     // not on ground, so little effect on velocity
  675.     PM_Accelerate (wishdir, wishspeed, pm_airaccelerate);
  676.  
  677.     // we may have a ground plane that is very steep, even
  678.     // though we don't have a groundentity
  679.     // slide along the steep plane
  680.     if ( pml.groundPlane ) {
  681.         PM_ClipVelocity (pm->ps->velocity, pml.groundTrace.plane.normal, 
  682.             pm->ps->velocity, OVERCLIP );
  683.     }
  684.  
  685.     PM_StepSlideMove ( qtrue );
  686. }
  687.  
  688. /*
  689. ===================
  690. PM_WalkMove
  691. ===================
  692. */
  693. static void PM_WalkMove( void ) {
  694.     int            i;
  695.     vec3_t        wishvel;
  696.     float        fmove, smove;
  697.     vec3_t        wishdir;
  698.     float        wishspeed;
  699.     float        scale;
  700.     usercmd_t    cmd;
  701.     float        accelerate;
  702.     float        vel;
  703.  
  704.     if ( pm->waterlevel > 2 && DotProduct( pml.forward, pml.groundTrace.plane.normal ) > 0 ) 
  705.     {
  706.         // begin swimming
  707.         PM_WaterMove();
  708.         return;
  709.     }
  710.  
  711.  
  712.     if ( PM_CheckJump () )
  713.     {
  714.         PM_BeginZoomOut ( );
  715.  
  716.         // jumped away
  717.         if ( pm->waterlevel > 1 ) 
  718.         {
  719.             PM_WaterMove();
  720.         } 
  721.         else 
  722.         {
  723.             PM_AirMove();
  724.         }
  725.         return;
  726.     }
  727.  
  728.     PM_Friction ();
  729.  
  730.     fmove = pm->cmd.forwardmove;
  731.     smove = pm->cmd.rightmove;
  732.  
  733.     cmd = pm->cmd;
  734.     scale = PM_CmdScale( &cmd );
  735.  
  736.     // set the movementDir so clients can rotate the legs for strafing
  737.     PM_SetMovementDir();
  738.  
  739.     // project moves down to flat plane
  740.     pml.forward[2] = 0;
  741.     pml.right[2] = 0;
  742.  
  743.     // project the forward and right directions onto the ground plane
  744.     PM_ClipVelocity (pml.forward, pml.groundTrace.plane.normal, pml.forward, OVERCLIP );
  745.     PM_ClipVelocity (pml.right, pml.groundTrace.plane.normal, pml.right, OVERCLIP );
  746.     //
  747.     VectorNormalize (pml.forward);
  748.     VectorNormalize (pml.right);
  749.  
  750.     for ( i = 0 ; i < 3 ; i++ ) {
  751.         wishvel[i] = pml.forward[i]*fmove + pml.right[i]*smove;
  752.     }
  753.     // when going up or down slopes the wish velocity should Not be zero
  754. //    wishvel[2] = 0;
  755.  
  756.     VectorCopy (wishvel, wishdir);
  757.     wishspeed = VectorNormalize(wishdir);
  758.     wishspeed *= scale;
  759.  
  760.     // clamp the speed lower if ducking
  761.     if ( pm->ps->pm_flags & PMF_DUCKED ) {
  762.         if ( wishspeed > pm->ps->speed * pm_duckScale ) {
  763.             wishspeed = pm->ps->speed * pm_duckScale;
  764.         }
  765.     }
  766.  
  767.     // clamp the speed lower if wading or walking on the bottom
  768.     if ( pm->waterlevel && !(pm->watertype & CONTENTS_LADDER) ) {
  769.         float    waterScale;
  770.  
  771.         waterScale = pm->waterlevel / 3.0;
  772.         waterScale = 1.0 - ( 1.0 - pm_swimScale ) * waterScale;
  773.         if ( wishspeed > pm->ps->speed * waterScale ) {
  774.             wishspeed = pm->ps->speed * waterScale;
  775.         }
  776.     }
  777.  
  778.     // when a player gets hit, they temporarily lose
  779.     // full control, which allows them to be moved a bit
  780.     if ( ( pml.groundTrace.surfaceFlags & SURF_SLICK ) || pm->ps->pm_flags & PMF_TIME_KNOCKBACK ) 
  781.     {
  782.         accelerate = pm_airaccelerate;
  783.     } 
  784.     else 
  785.     {
  786.         accelerate = pm_accelerate;
  787.  
  788.         // Accelerate faster when ducked
  789.         if ( pm->ps->pm_flags & PMF_DUCKED ) 
  790.         {
  791.             accelerate *= 2;
  792.         }
  793.     }
  794.  
  795.     PM_Accelerate (wishdir, wishspeed, accelerate);
  796.  
  797.     if ( ( pml.groundTrace.surfaceFlags & SURF_SLICK ) || pm->ps->pm_flags & PMF_TIME_KNOCKBACK ) 
  798.     {
  799.         pm->ps->velocity[2] -= pm->ps->gravity * pml.frametime;
  800.     } 
  801.  
  802.     vel = VectorLength(pm->ps->velocity);
  803.  
  804.     // slide along the ground plane
  805.     PM_ClipVelocity (pm->ps->velocity, pml.groundTrace.plane.normal, 
  806.         pm->ps->velocity, OVERCLIP );
  807.  
  808.     // don't decrease velocity when going up or down a slope
  809.     VectorNormalize(pm->ps->velocity);
  810.     VectorScale(pm->ps->velocity, vel, pm->ps->velocity);
  811.  
  812.     // don't do anything if standing still
  813.     if (!pm->ps->velocity[0] && !pm->ps->velocity[1]) 
  814.     {
  815.         return;
  816.     }
  817.  
  818.     PM_StepSlideMove( qfalse );
  819. }
  820.  
  821. /*
  822. ===================
  823. PM_LadderMove
  824. ===================
  825. */
  826. static void PM_LadderMove ( void ) 
  827. {
  828.     float    wishspeed;
  829.     float    scale;
  830.     vec3_t    wishdir;
  831.     vec3_t    wishvel;
  832.     float    accelerate;
  833.  
  834.     if ( PM_CheckJump () )
  835.     {
  836.         return;
  837.     }
  838.  
  839.     PM_Friction ();
  840.  
  841.     scale = PM_CmdScale( &pm->cmd );
  842.  
  843.     accelerate = pm_accelerate;
  844.  
  845.     //
  846.     // user intentions
  847.     //
  848.     if ( !scale ) 
  849.     {
  850.         wishvel[0] = 0;
  851.         wishvel[1] = 0;
  852.         wishvel[2] = 0;
  853.     } 
  854.     else 
  855.     {
  856.         int i;
  857.         
  858.         VectorNormalize ( pm_ladders[pm->ps->ladder].fwd );
  859.         VectorNormalize ( pml.forward );
  860.  
  861.         if ( !pml.groundPlane )
  862.         {
  863.             vec3_t    mins;
  864.             vec3_t    maxs;
  865.             vec3_t    offset = {1, 1, 1};
  866.             trace_t tr;
  867.  
  868.             VectorCopy ( pm->mins, mins );
  869.             VectorSubtract ( mins, offset, mins );
  870.             VectorCopy ( pm->maxs, maxs );
  871.             VectorAdd ( maxs, offset, maxs );
  872.  
  873.             pm->trace ( &tr, pm->ps->origin, mins, maxs, pm->ps->origin, pm->ps->clientNum, pm->tracemask );
  874.             if ( tr.fraction == 1.0f || !tr.startsolid )
  875.             {
  876.                 if ( pm->cmd.forwardmove >= 0 )
  877.                 {
  878.                     VectorAdd ( pml.forward, pm_ladders[pm->ps->ladder].fwd, pml.forward );
  879.                 }
  880.                 else
  881.                 {
  882.                     VectorSubtract ( pml.forward, pm_ladders[pm->ps->ladder].fwd, pml.forward );
  883.                 }
  884.             }
  885.         }
  886.  
  887.         for ( i=0 ; i<3 ; i++ ) 
  888.         {
  889.             wishvel[i] = scale * pml.forward[i]*pm->cmd.forwardmove + scale * pml.right[i]*pm->cmd.rightmove * pm_ladderScale;
  890.         }
  891.  
  892.         // Duck down ladders
  893.         if ( pm->cmd.upmove < 0 )
  894.         {
  895.             wishvel[2] += scale * pm->cmd.upmove;
  896.         }
  897.     }
  898.  
  899.     VectorCopy (wishvel, wishdir);
  900.     wishspeed = VectorNormalize(wishdir);
  901.  
  902.     PM_Accelerate( wishdir, wishspeed, accelerate );
  903.  
  904.     PM_StepSlideMove( qfalse );
  905. }
  906.  
  907. /*
  908. ==============
  909. PM_DeadMove
  910. ==============
  911. */
  912. static void PM_DeadMove( void ) {
  913.     float    forward;
  914.  
  915.     if ( !pml.walking ) {
  916.         return;
  917.     }
  918.  
  919.     // extra friction
  920.  
  921.     forward = VectorLength (pm->ps->velocity);
  922.     forward -= 20;
  923.     if ( forward <= 0 ) {
  924.         VectorClear (pm->ps->velocity);
  925.     } else {
  926.         VectorNormalize (pm->ps->velocity);
  927.         VectorScale (pm->ps->velocity, forward, pm->ps->velocity);
  928.     }
  929. }
  930.  
  931.  
  932. /*
  933. ===============
  934. PM_NoclipMove
  935. ===============
  936. */
  937. static void PM_NoclipMove( void ) {
  938.     float    speed, drop, friction, control, newspeed;
  939.     int            i;
  940.     vec3_t        wishvel;
  941.     float        fmove, smove;
  942.     vec3_t        wishdir;
  943.     float        wishspeed;
  944.     float        scale;
  945.  
  946.     pm->ps->viewheight = DEFAULT_VIEWHEIGHT;
  947.  
  948.     // friction
  949.  
  950.     speed = VectorLength (pm->ps->velocity);
  951.     if (speed < 1)
  952.     {
  953.         VectorCopy (vec3_origin, pm->ps->velocity);
  954.     }
  955.     else
  956.     {
  957.         drop = 0;
  958.  
  959.         friction = pm_friction*1.5;    // extra friction
  960.         control = speed < pm_stopspeed ? pm_stopspeed : speed;
  961.         drop += control*friction*pml.frametime;
  962.  
  963.         // scale the velocity
  964.         newspeed = speed - drop;
  965.         if (newspeed < 0)
  966.             newspeed = 0;
  967.         newspeed /= speed;
  968.  
  969.         VectorScale (pm->ps->velocity, newspeed, pm->ps->velocity);
  970.     }
  971.  
  972.     // accelerate
  973.     scale = PM_CmdScale( &pm->cmd );
  974.  
  975.     scale *= 1.5f;
  976.  
  977.     fmove = pm->cmd.forwardmove;
  978.     smove = pm->cmd.rightmove;
  979.     
  980.     for (i=0 ; i<3 ; i++)
  981.         wishvel[i] = pml.forward[i]*fmove + pml.right[i]*smove;
  982.     wishvel[2] += pm->cmd.upmove;
  983.  
  984.     VectorCopy (wishvel, wishdir);
  985.     wishspeed = VectorNormalize(wishdir);
  986.     wishspeed *= scale;
  987.  
  988.     PM_Accelerate( wishdir, wishspeed, pm_flyaccelerate );
  989.  
  990.     // move
  991.     VectorMA (pm->ps->origin, pml.frametime, pm->ps->velocity, pm->ps->origin);
  992. }
  993.  
  994. //============================================================================
  995.  
  996. /*
  997. ==============
  998. PM_Use
  999.  
  1000. Generates a use event
  1001. ==============
  1002. */
  1003. #define USE_DELAY 2000
  1004.  
  1005. void PM_Use( void ) 
  1006. {
  1007.     int useTime = 0;
  1008.  
  1009.     // don't allow attack until all buttons are up
  1010.     if ( pm->ps->pm_flags & PMF_RESPAWNED ) 
  1011.     {
  1012.         return;
  1013.     }
  1014.  
  1015.     // ignore if not a normal player
  1016.     if ( pm->ps->pm_type != PM_NORMAL ) 
  1017.     {
  1018.         return;
  1019.     }
  1020.  
  1021.     // check for dead player
  1022.     if ( pm->ps->stats[STAT_HEALTH] <= 0 ) 
  1023.     {
  1024.         pm->ps->weapon = WP_NONE;
  1025.         return;
  1026.     }
  1027.  
  1028.     // Cant use so dont bother letting them try
  1029.  
  1030.     if ( !(pm->ps->pm_flags & PMF_CAN_USE ) || !(pm->cmd.buttons & BUTTON_USE ) )
  1031.     {
  1032.         if ( pm->ps->stats[STAT_USEWEAPONDROP] )
  1033.         {
  1034.             pm->ps->stats[STAT_USEWEAPONDROP] -= pml.msec;
  1035.             if ( pm->ps->stats[STAT_USEWEAPONDROP] < 0 )
  1036.             {
  1037.                 pm->ps->stats[STAT_USEWEAPONDROP] = 0;
  1038.             }
  1039.         }
  1040.  
  1041.         if ( pm->ps->pm_debounce & PMD_USE )
  1042.         {
  1043.             pm->ps->pm_debounce &= ~PMD_USE;
  1044.             pm->ps->stats[STAT_USETIME] = 0;
  1045.         }
  1046.         return;
  1047.     }
  1048.  
  1049.     pm->ps->pm_debounce |= PMD_USE;
  1050.  
  1051.     useTime = pm->ps->stats[STAT_USETIME_MAX];
  1052.     if ( useTime )
  1053.     {
  1054.         int elapsedTime = pm->ps->stats[STAT_USETIME];
  1055.  
  1056.         if ( elapsedTime < useTime )
  1057.         {
  1058.             elapsedTime += pml.msec;
  1059.         }
  1060.         
  1061.         pm->ps->stats[STAT_USEWEAPONDROP] += pml.msec;
  1062.         if ( pm->ps->stats[STAT_USEWEAPONDROP] > 300 )
  1063.         {
  1064.             pm->ps->stats[STAT_USEWEAPONDROP] = 300;
  1065.         }
  1066.  
  1067.         if ( elapsedTime >= useTime )
  1068.         {
  1069.             pm->ps->stats[STAT_USETIME] = 0;
  1070.             PM_AddEvent ( EV_USE );
  1071.         }
  1072.         else
  1073.         {
  1074.             pm->ps->stats[STAT_USETIME] = elapsedTime;
  1075.         }
  1076.  
  1077.         return;
  1078.     }    
  1079.  
  1080.     if ( !(pm->ps->pm_debounce & PMD_USE) )
  1081.     {
  1082.         PM_AddEvent ( EV_USE );
  1083.     }
  1084. }
  1085.  
  1086.  
  1087. /*
  1088. ================
  1089. PM_FootstepForSurface
  1090.  
  1091. Returns an event number apropriate for the groundsurface
  1092. ================
  1093. */
  1094. static void PM_FootstepForSurface( void ) 
  1095. {
  1096.     if ( pml.groundTrace.surfaceFlags & SURF_NOSTEPS ) 
  1097.     {
  1098.         return;
  1099.     }
  1100.  
  1101.     PM_AddEventWithParm(EV_FOOTSTEP, pml.groundTrace.surfaceFlags & MATERIAL_MASK);
  1102. }
  1103.  
  1104.  
  1105. /*
  1106. =================
  1107. PM_CrashLand
  1108.  
  1109. Check for hard landings that generate sound events
  1110. =================
  1111. */
  1112.  
  1113. int    minDeltaForDmg                = 97;
  1114. int minDeltaForSmallPainSound    = 30;
  1115. int minDeltaForBigPainSound        = 97;
  1116. int minDeltaForSlowDown            = 17;
  1117.  
  1118. static void PM_CrashLand( int impactMaterial, vec3_t impactNormal ) 
  1119. {
  1120.     float        delta;
  1121.     float        dist;
  1122.     float        vel, acc;
  1123.     float        t;
  1124.     float        a, b, c, den;
  1125.     float        f;
  1126.     int            scaleDelta;
  1127.     qboolean    jumped;
  1128.  
  1129.     static vec3_t up = {0,0,1};
  1130.  
  1131.     // were they juping?
  1132.     jumped = (pm->ps->pm_flags&PMF_JUMPING) ? qtrue : qfalse;
  1133.  
  1134.     pm->ps->pm_flags &= (~PMF_LADDER_JUMP);
  1135.     pm->ps->pm_flags &= (~PMF_JUMPING);
  1136.  
  1137.     // calculate the exact velocity on landing
  1138.     dist = pm->ps->origin[2] - pml.previous_origin[2];
  1139.     vel = pml.previous_velocity[2];
  1140.     acc = -pm->ps->gravity;
  1141.  
  1142.     a = acc / 2;
  1143.     b = vel;
  1144.     c = -dist;
  1145.  
  1146.     den =  b * b - 4 * a * c;
  1147.     if ( den < 0 ) 
  1148.     {
  1149.         return;
  1150.     }
  1151.  
  1152.     t = (-b - sqrt( den ) ) / ( 2 * a );
  1153.  
  1154.     delta = vel + t * acc;
  1155.     delta = delta * delta * 0.000275f;
  1156.  
  1157.     switch ( pm->waterlevel )
  1158.     {
  1159.         case 3:
  1160.             // never take falling damage if completely underwater
  1161.             return;
  1162.  
  1163.         // reduce falling damage if there is standing water
  1164.         case 2:
  1165.             delta *= 0.25;
  1166.             break;
  1167.  
  1168.         // reduce falling damage if there is standing water
  1169.         case 1:
  1170.             delta *= 0.5;
  1171.             break;
  1172.     }
  1173.  
  1174.     // Scale the delta based on the normal of the plane we hit
  1175.     f = DotProduct ( up, impactNormal );
  1176.     if ( f < .25 )
  1177.     {
  1178.         delta *= f;
  1179.     }
  1180.  
  1181.     // Just hit the ground, no more z velocity or we could bounce
  1182.     pm->ps->velocity[2] = 0;
  1183.  
  1184.     // start footstep cycle over if it wasnt a little jump
  1185.     if ( delta > minDeltaForSlowDown )
  1186.     {
  1187.         pm->ps->bobCycle = 0;
  1188.     }
  1189.  
  1190.     if ( delta < 1 ) 
  1191.     {
  1192.         return;
  1193.     }
  1194.     else if ( jumped && delta >= minDeltaForSlowDown )
  1195.     {
  1196.         // Cut their forward velocity, this pretty much eliminates strafe jumping
  1197.          pm->ps->velocity[0] *= 0.25f;
  1198.         pm->ps->velocity[1] *= 0.25f;
  1199.  
  1200.         pm->ps->pm_time = 500;
  1201.     }
  1202.  
  1203.     // create a local entity event to play the sound
  1204.  
  1205.     // SURF_NODAMAGE is used for bounce pads where you don't ever
  1206.     // want to take damage or play a crunch sound
  1207.     scaleDelta = (int)delta;
  1208.     if (scaleDelta > 100 + minDeltaForDmg)
  1209.     {
  1210.         scaleDelta = 100 + minDeltaForDmg;
  1211.     }
  1212.     scaleDelta -= minDeltaForDmg;
  1213.     if ( !(pml.groundTrace.surfaceFlags & SURF_NODAMAGE) )  
  1214.     {
  1215.         if ( delta > minDeltaForBigPainSound ) 
  1216.         {
  1217.             PM_AddEventWithParm(EV_FALL_FAR, scaleDelta | ((impactMaterial & MATERIAL_MASK)<<8));
  1218.         } 
  1219.         else if ( delta > minDeltaForDmg ) 
  1220.         {
  1221.             // this is a pain grunt, so don't play it if dead
  1222.             if ( pm->ps->stats[STAT_HEALTH] > 0 ) 
  1223.             {
  1224.                 PM_AddEventWithParm(EV_FALL_MEDIUM, scaleDelta | ((impactMaterial & MATERIAL_MASK)<<8));
  1225.             }
  1226.         } 
  1227.         else if ( delta > minDeltaForSlowDown ) 
  1228.         {
  1229.             PM_AddEventWithParm(EV_FALL_SHORT, impactMaterial & MATERIAL_MASK );
  1230.         } 
  1231.         else if ( delta > 10 && (pm->cmd.buttons & BUTTON_WALKING) )
  1232.         {
  1233.             PM_FootstepForSurface();
  1234.         }
  1235.     }
  1236. }
  1237.  
  1238. /*
  1239. =============
  1240. PM_CorrectAllSolid
  1241. =============
  1242. */
  1243. static int PM_CorrectAllSolid( trace_t *trace ) 
  1244. {
  1245.     int            i, j, k;
  1246.     vec3_t        point;
  1247.  
  1248.     if ( pm->debugLevel ) 
  1249.     {
  1250.         Com_Printf("%i:allsolid\n", c_pmove);
  1251.     }
  1252.  
  1253.     // jitter around
  1254.     for (i = -1; i <= 1; i++) {
  1255.         for (j = -1; j <= 1; j++) {
  1256.             for (k = -1; k <= 1; k++) {
  1257.                 VectorCopy(pm->ps->origin, point);
  1258.                 point[0] += (float) i;
  1259.                 point[1] += (float) j;
  1260.                 point[2] += (float) k;
  1261.                 pm->trace (trace, point, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask);
  1262.                 if ( !trace->allsolid ) {
  1263.                     point[0] = pm->ps->origin[0];
  1264.                     point[1] = pm->ps->origin[1];
  1265.                     point[2] = pm->ps->origin[2] - 0.25;
  1266.  
  1267.                     pm->trace (trace, pm->ps->origin, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask);
  1268.                     pml.groundTrace = *trace;
  1269.                     return qtrue;
  1270.                 }
  1271.             }
  1272.         }
  1273.     }
  1274.  
  1275.     pm->ps->groundEntityNum = ENTITYNUM_NONE;
  1276.     pml.groundPlane = qfalse;
  1277.     pml.walking = qfalse;
  1278.  
  1279.     return qfalse;
  1280. }
  1281.  
  1282.  
  1283. /*
  1284. =============
  1285. PM_GroundTraceMissed
  1286.  
  1287. The ground trace didn't hit a surface, so we are in freefall
  1288. =============
  1289. */
  1290. static void PM_GroundTraceMissed( void ) 
  1291. {
  1292.     trace_t        trace;
  1293.     vec3_t        point;
  1294.  
  1295.     if ( pm->ps->groundEntityNum != ENTITYNUM_NONE ) 
  1296.     {
  1297.         // we just transitioned into freefall
  1298.         if ( pm->debugLevel ) 
  1299.         {
  1300.             Com_Printf("%i:lift\n", c_pmove);
  1301.         }
  1302.  
  1303.         // if they aren't in a jumping animation and the ground is a ways away, force into it
  1304.         // if we didn't do the trace, the player would be backflipping down staircases
  1305.         VectorCopy( pm->ps->origin, point );
  1306.         point[2] -= 64;
  1307.  
  1308.         pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask);
  1309.         if ( trace.fraction == 1.0 ) 
  1310.         {
  1311.             if ( pm->cmd.forwardmove >= 0 ) 
  1312.             {
  1313.                 pm->ps->pm_flags &= ~PMF_BACKWARDS_JUMP;
  1314.             } 
  1315.             else 
  1316.             {
  1317.                 pm->ps->pm_flags |= PMF_BACKWARDS_JUMP;
  1318.             }
  1319.         }
  1320.     }
  1321.  
  1322.     pm->ps->groundEntityNum = ENTITYNUM_NONE;
  1323.     pml.groundPlane = qfalse;
  1324.     pml.walking = qfalse;
  1325. }
  1326.  
  1327.  
  1328. /*
  1329. =============
  1330. PM_GroundTrace
  1331. =============
  1332. */
  1333. static void PM_GroundTrace( void ) 
  1334. {
  1335.     vec3_t        point;
  1336.     trace_t        trace;
  1337.     float        minWalkNormal;
  1338.  
  1339.     point[0] = pm->ps->origin[0];
  1340.     point[1] = pm->ps->origin[1];
  1341.     point[2] = pm->ps->origin[2] - 0.25;
  1342.  
  1343.     pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask);
  1344.     pml.groundTrace = trace;
  1345.  
  1346.     // When stuck to antoher player set a flag to let the trigger code know so it can unstick the player
  1347.     if ( (trace.allsolid || trace.startsolid) && trace.entityNum < MAX_CLIENTS ) 
  1348.     {
  1349.         pm->ps->pm_flags |= PMF_SIAMESETWINS;
  1350.     }
  1351.  
  1352.     // if the trace didn't hit anything, we are in free fall
  1353.     if ( trace.fraction == 1.0 ) {
  1354.         PM_GroundTraceMissed();
  1355.         pml.groundPlane = qfalse;
  1356.         pml.walking = qfalse;
  1357.         return;
  1358.     }
  1359.  
  1360.     // check if getting thrown off the ground
  1361.     if ( pm->ps->velocity[2] > 0 && DotProduct( pm->ps->velocity, trace.plane.normal ) > 10 ) {
  1362.         if ( pm->debugLevel ) {
  1363.             Com_Printf("%i:kickoff\n", c_pmove);
  1364.         }
  1365.         // go into jump animation
  1366.         if ( pm->cmd.forwardmove >= 0 ) {
  1367.             PM_ForceLegsAnim( pm->ps, LEGS_JUMP );
  1368.             pm->ps->pm_flags &= ~PMF_BACKWARDS_JUMP;
  1369.         } else {
  1370.             PM_ForceLegsAnim( pm->ps, LEGS_JUMP_BACK );
  1371.             pm->ps->pm_flags |= PMF_BACKWARDS_JUMP;
  1372.         }
  1373.  
  1374.         pm->ps->groundEntityNum = ENTITYNUM_NONE;
  1375.         pml.groundPlane = qfalse;
  1376.         pml.walking = qfalse;
  1377.         return;
  1378.     }
  1379.     
  1380.     // slopes that are too steep will not be considered onground
  1381.     if ( trace.contents & CONTENTS_TERRAIN )
  1382.     {
  1383.         minWalkNormal = MIN_WALK_NORMAL_TERRAIN;
  1384.     }
  1385.     else
  1386.     {
  1387.         minWalkNormal = MIN_WALK_NORMAL;
  1388.     }
  1389.  
  1390.     if ( trace.plane.normal[2] < minWalkNormal ) 
  1391.     {
  1392.         if ( pm->debugLevel ) 
  1393.         {
  1394.             Com_Printf("%i:steep\n", c_pmove);
  1395.         }
  1396.  
  1397.         // FIXME: if they can't slide down the slope, let them
  1398.         // walk (sharp crevices)
  1399.         pm->ps->groundEntityNum = ENTITYNUM_NONE;
  1400.         pml.groundPlane = qtrue;
  1401.         pml.walking = qfalse;
  1402.         return;
  1403.     }
  1404.  
  1405.     pml.groundPlane = qtrue;
  1406.     pml.walking = qtrue;
  1407.  
  1408.     // hitting solid ground will end a waterjump
  1409.     if (pm->ps->pm_flags & PMF_TIME_WATERJUMP)
  1410.     {
  1411.         pm->ps->pm_flags &= ~(PMF_TIME_WATERJUMP | PMF_TIME_LAND);
  1412.         pm->ps->pm_time = 0;
  1413.     }
  1414.  
  1415.     if ( pm->ps->groundEntityNum == ENTITYNUM_NONE) 
  1416.     {
  1417.         // just hit the ground
  1418. //        if ((pml.groundTrace.contents & CONTENTS_TERRAIN) && pml.previous_velocity[2] > -200)
  1419. //        {
  1420. //        }
  1421. //        else
  1422.         {
  1423.             if ( pm->debugLevel ) 
  1424.             {
  1425.                 Com_Printf("%i:Land\n", c_pmove);
  1426.             }
  1427.             
  1428.             PM_CrashLand(trace.surfaceFlags & MATERIAL_MASK, trace.plane.normal );
  1429.  
  1430.             // don't do landing time if we were just going down a slope
  1431.             if ( pml.previous_velocity[2] < -200 ) 
  1432.             {
  1433.                 // don't allow another jump for a little while
  1434.                 pm->ps->pm_flags |= PMF_TIME_LAND;
  1435.                 pm->ps->pm_time = 250;
  1436.             }
  1437.         }
  1438.     }
  1439.  
  1440.     pm->ps->groundEntityNum = trace.entityNum;
  1441.  
  1442.     // don't reset the z velocity for slopes
  1443. //    pm->ps->velocity[2] = 0;
  1444.  
  1445.     PM_AddTouchEnt( trace.entityNum );
  1446. }
  1447.  
  1448.  
  1449. /*
  1450. =============
  1451. PM_SetWaterLevel    FIXME: avoid this twice?  certainly if not moving
  1452. =============
  1453. */
  1454. static void PM_SetWaterLevel( void ) 
  1455. {
  1456.     vec3_t        point;
  1457.     int            cont;
  1458.     int            sample1;
  1459.     int            sample2;
  1460.  
  1461.     //
  1462.     // get waterlevel, accounting for ducking
  1463.     //
  1464.     pm->waterlevel = 0;
  1465.     pm->watertype  = 0;
  1466.  
  1467.     point[0] = pm->ps->origin[0];
  1468.     point[1] = pm->ps->origin[1];
  1469.     point[2] = pm->ps->origin[2] + pm->mins[2];    
  1470.     cont = pm->pointcontents( point, pm->ps->clientNum );
  1471.  
  1472.     // See if we are on a ladder too
  1473.     if ( !(pm->ps->pm_flags&PMF_LADDER_JUMP) && (cont & CONTENTS_LADDER) )
  1474.     {
  1475.         if ( pm->ps->ladder == -1 )
  1476.         {
  1477.              pm->ps->ladder = BG_FindLadder ( pm->ps->origin );
  1478.         }
  1479.  
  1480.         pm->ps->pm_flags |= PMF_LADDER;
  1481.     }
  1482.     else
  1483.     {
  1484.         pm->ps->ladder = -1;
  1485.         pm->ps->pm_flags &= ~PMF_LADDER;
  1486.     }
  1487.  
  1488.     if ( cont & MASK_WATER ) 
  1489.     {
  1490.         sample2 = pm->ps->viewheight - MINS_Z;
  1491.         sample1 = sample2 / 2;
  1492.  
  1493.         pm->watertype = cont;
  1494.         pm->waterlevel = 1;
  1495.         point[2] = pm->ps->origin[2] + MINS_Z + sample1;
  1496.         cont = pm->pointcontents (point, pm->ps->clientNum );
  1497.         if ( cont & MASK_WATER ) 
  1498.         {
  1499.             pm->waterlevel = 2;
  1500.             point[2] = pm->ps->origin[2] + MINS_Z + sample2;
  1501.             cont = pm->pointcontents (point, pm->ps->clientNum );
  1502.             if ( cont & MASK_WATER )
  1503.             {
  1504.                 pm->waterlevel = 3;
  1505.             }
  1506.         }
  1507.     }
  1508. }
  1509.  
  1510. /*
  1511. ==============
  1512. PM_CheckCrouchJump
  1513.  
  1514. Handles crouch jumping
  1515. ==============
  1516. */
  1517. static void PM_CheckCrouchJump ( void )
  1518. {
  1519.     // Already crouch jumping so check to see if its over
  1520.     if ( pm->ps->pm_flags & PMF_CROUCH_JUMP )
  1521.     {
  1522.         // If they are on the ground the crouch jump is over
  1523.         if ( pml.groundPlane )
  1524.         {
  1525.             pm->ps->pm_flags &= ~PMF_CROUCH_JUMP;
  1526.         }
  1527.     }
  1528.     else
  1529.     {
  1530.         // If not on the ground and still heading up then crouch jump is possible.
  1531.         if ( !pml.groundPlane && (pm->ps->pm_flags & PMF_JUMPING) && pm->cmd.upmove < 0 )
  1532.         {
  1533.             pm->ps->pm_flags |= PMF_CROUCH_JUMP;
  1534.         }
  1535.     }
  1536.  
  1537.     // Check again if still crouch jumping and if so alter the view height
  1538.     // so the client doesnt look like they are ducking in mid air
  1539.     if ( (pm->ps->pm_flags & PMF_CROUCH_JUMP) && (pm->ps->pm_flags & PMF_JUMPING) )
  1540.     {
  1541.         // If still ducked look for windows
  1542.         if ( pm->ps->pm_flags & PMF_DUCKED )
  1543.         {
  1544.             trace_t trace;
  1545.             vec3_t  maxs;
  1546.  
  1547.             VectorCopy ( pm->maxs, maxs );
  1548.             maxs[2] = DEFAULT_PLAYER_Z_MAX;
  1549.  
  1550.             pm->trace (&trace, pm->ps->origin, pm->mins, maxs, pm->ps->origin, pm->ps->clientNum, pm->tracemask );
  1551.             if ( !(trace.allsolid || trace.startsolid) )
  1552.             {
  1553.                 pm->ps->viewheight = DEFAULT_VIEWHEIGHT;
  1554.             }
  1555.         }
  1556.     }
  1557. }
  1558.  
  1559. /*
  1560. ==============
  1561. PM_CheckDuck
  1562.  
  1563. Sets mins, maxs, and pm->ps->viewheight
  1564. ==============
  1565. */
  1566. static void PM_CheckDuck (void)
  1567. {
  1568.     trace_t    trace;
  1569.  
  1570.     if ( (pm == 0) || (pm->ps == 0) )
  1571.     {
  1572.         return;
  1573.     }
  1574.  
  1575.     pm->mins[0] = -15;
  1576.     pm->mins[1] = -15;
  1577.  
  1578.     pm->maxs[0] = 15;
  1579.     pm->maxs[1] = 15;
  1580.  
  1581.     pm->mins[2] = MINS_Z;
  1582.     
  1583.     if (pm->ps->pm_type == PM_DEAD)
  1584.     {
  1585.         pm->maxs[2] = DEAD_PLAYER_Z_MAX;
  1586.         pm->ps->viewheight = DEAD_VIEWHEIGHT;
  1587.         return;
  1588.     }
  1589.  
  1590.     // duck or prone
  1591.     if (pm->cmd.upmove < 0)
  1592.     {
  1593.         // assume ducked at first
  1594.         pm->ps->pm_flags |= PMF_DUCKED;        
  1595.     }
  1596.     else
  1597.     {    // stand up if possible
  1598.         if ( pm->ps->pm_flags & PMF_DUCKED )
  1599.         {
  1600.             pm->maxs[2] = DEFAULT_PLAYER_Z_MAX;
  1601.             pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, pm->ps->origin, pm->ps->clientNum, pm->tracemask );
  1602.             if (!trace.allsolid)
  1603.             {
  1604.                 pm->ps->pm_flags &= ~PMF_DUCKED;
  1605.             }
  1606.         }
  1607.     }
  1608.  
  1609.     if ( (pm->ps->pm_flags & PMF_DUCKED) )
  1610.     {
  1611.         pm->maxs[2] = CROUCH_PLAYER_Z_MAX;
  1612.         pm->ps->viewheight = CROUCH_VIEWHEIGHT;
  1613.     }
  1614.     else
  1615.     {
  1616.         pm->maxs[2] = DEFAULT_PLAYER_Z_MAX;
  1617.         pm->ps->viewheight = DEFAULT_VIEWHEIGHT;
  1618.     }
  1619. }
  1620.  
  1621. /*
  1622. ===============
  1623. PM_Footsteps
  1624. ===============
  1625. */
  1626. static void PM_Footsteps( void ) 
  1627. {
  1628.     float        bobmove;
  1629.     int            old;
  1630.     qboolean    footstep;
  1631.  
  1632.     //
  1633.     // calculate speed and cycle to be used for
  1634.     // all cyclic walking effects
  1635.     //
  1636.     pm->xyspeed = sqrt( pm->ps->velocity[0] * pm->ps->velocity[0]
  1637.         +  pm->ps->velocity[1] * pm->ps->velocity[1] );
  1638.  
  1639.     if ( pm->ps->groundEntityNum == ENTITYNUM_NONE ) 
  1640.     {
  1641.  
  1642.         if ( pm->ps->pm_flags & PMF_LADDER )
  1643.         {
  1644.         }
  1645.         else
  1646.         {
  1647.         // airborne leaves position in cycle intact, but doesn't advance
  1648.             if ( pm->waterlevel > 1 ) 
  1649.             {
  1650.                 PM_ContinueLegsAnim( pm->ps, LEGS_SWIM );
  1651.             }
  1652.             return;
  1653.         }
  1654.     }
  1655.  
  1656.     // if not trying to move
  1657.     if ( !pm->cmd.forwardmove && !pm->cmd.rightmove ) 
  1658.     {
  1659.         if (  pm->xyspeed < 5 ) 
  1660.         {
  1661.             pm->ps->bobCycle = 0;    // start at beginning of cycle again
  1662.             
  1663.             if ( pm->ps->pm_flags & PMF_DUCKED ) 
  1664.             {
  1665.                 if ( pm->ps->leanTime - LEAN_TIME < 0 )
  1666.                 {
  1667.                     PM_ContinueLegsAnim( pm->ps, LEGS_LEAN_CROUCH_LEFT );    
  1668.                 }
  1669.                 else if ( pm->ps->leanTime - LEAN_TIME > 0 )
  1670.                 {
  1671.                     PM_ContinueLegsAnim( pm->ps, LEGS_LEAN_CROUCH_RIGHT );    
  1672.                 }
  1673.                 else
  1674.                 {
  1675.                     PM_ContinueLegsAnim( pm->ps, LEGS_IDLE_CROUCH );
  1676.                 }
  1677.             }        
  1678.             else 
  1679.             {
  1680.                 if ( pm->ps->leanTime - LEAN_TIME < 0 )
  1681.                 {
  1682.                     PM_ContinueLegsAnim( pm->ps, LEGS_LEAN_LEFT );    
  1683.                 }
  1684.                 else if ( pm->ps->leanTime - LEAN_TIME > 0 )
  1685.                 {
  1686.                     PM_ContinueLegsAnim( pm->ps, LEGS_LEAN_RIGHT );    
  1687.                 }
  1688.                 else
  1689.                 {
  1690.                     PM_ContinueLegsAnim( pm->ps, TORSO_IDLE_PISTOL );
  1691.                 }
  1692.             }
  1693.         }
  1694.         return;
  1695.     }
  1696.     
  1697.  
  1698.     footstep = qfalse;
  1699.  
  1700.     if ( (pm->ps->pm_flags & PMF_DUCKED) && (pm->ps->groundEntityNum != ENTITYNUM_NONE ) ) 
  1701.     {
  1702.         bobmove = 0.25;    // ducked characters bob much faster
  1703.         
  1704.         if ( pm->ps->pm_flags & PMF_BACKWARDS_RUN ) 
  1705.         {
  1706.             PM_ContinueLegsAnim( pm->ps, LEGS_WALK_CROUCH_BACK );
  1707.         }
  1708.         else 
  1709.         {
  1710.             if ( pm->ps->leanTime - LEAN_TIME < 0 )
  1711.             {
  1712.                 if ( pm->cmd.rightmove > 0 )
  1713.                 {
  1714.                     PM_ContinueLegsAnim( pm->ps, LEGS_LEANLEFT_CROUCH_WALKRIGHT );    
  1715.                 }
  1716.                 else
  1717.                 {
  1718.                     PM_ContinueLegsAnim( pm->ps, LEGS_LEANLEFT_CROUCH_WALKLEFT );    
  1719.                 }
  1720.             }
  1721.             else if ( pm->ps->leanTime - LEAN_TIME > 0 )
  1722.             {
  1723.                 if ( pm->cmd.rightmove > 0 )
  1724.                 {
  1725.                     PM_ContinueLegsAnim( pm->ps, LEGS_LEANRIGHT_CROUCH_WALKRIGHT );    
  1726.                 }
  1727.                 else
  1728.                 {
  1729.                     PM_ContinueLegsAnim( pm->ps, LEGS_LEANRIGHT_CROUCH_WALKLEFT );    
  1730.                 }
  1731.             }
  1732.             else
  1733.             {
  1734.                 PM_ContinueLegsAnim( pm->ps, LEGS_WALK_CROUCH );
  1735.             }
  1736.         }
  1737.     } 
  1738.     else 
  1739.     {
  1740.         if ( !( pm->cmd.buttons & BUTTON_WALKING ) )
  1741.         {
  1742.             PM_BeginZoomOut ( );
  1743.  
  1744.             bobmove = 0.4f;    // faster speeds bob faster
  1745.             if ( pm->ps->pm_flags & PMF_BACKWARDS_RUN ) 
  1746.             {
  1747.                 PM_ContinueLegsAnim( pm->ps, LEGS_RUN_BACK );
  1748.             }
  1749.             else 
  1750.             {
  1751.                 PM_ContinueLegsAnim( pm->ps, LEGS_RUN );
  1752.             }
  1753.             footstep = qtrue;
  1754.         } 
  1755.         else 
  1756.         {
  1757.             bobmove = 0.3f;    // walking bobs slow
  1758.             if ( pm->ps->pm_flags & PMF_BACKWARDS_RUN ) 
  1759.             {
  1760.                 PM_ContinueLegsAnim( pm->ps, LEGS_WALK_BACK );
  1761.             }
  1762.             else 
  1763.             {
  1764.                 if ( pm->ps->leanTime - LEAN_TIME < 0 )
  1765.                 {
  1766.                     if ( pm->cmd.rightmove > 0 )
  1767.                     {
  1768.                         PM_ContinueLegsAnim( pm->ps, LEGS_LEANLEFT_WALKRIGHT );    
  1769.                     }
  1770.                     else
  1771.                     {
  1772.                         PM_ContinueLegsAnim( pm->ps, LEGS_LEANLEFT_WALKLEFT );    
  1773.                     }
  1774.                 }
  1775.                 else if ( pm->ps->leanTime - LEAN_TIME > 0 )
  1776.                 {
  1777.                     if ( pm->cmd.rightmove > 0 )
  1778.                     {
  1779.                         PM_ContinueLegsAnim( pm->ps, LEGS_LEANRIGHT_WALKRIGHT );    
  1780.                     }
  1781.                     else
  1782.                     {
  1783.                         PM_ContinueLegsAnim( pm->ps, LEGS_LEANRIGHT_WALKLEFT );    
  1784.                     }
  1785.                 }
  1786.                 else
  1787.                 {
  1788.                     PM_ContinueLegsAnim( pm->ps, LEGS_WALK );
  1789.                 }
  1790.             }
  1791.         }
  1792.     }
  1793.  
  1794.     // check for footstep / splash sounds
  1795.     old = pm->ps->bobCycle;
  1796.     pm->ps->bobCycle = (int)( old + bobmove * pml.msec ) & 255;
  1797.  
  1798.     // if we just crossed a cycle boundary, play an apropriate footstep event
  1799.     if ( ( ( old + 64 ) ^ ( pm->ps->bobCycle + 64 ) ) & 128 ) 
  1800.     {
  1801.         if ( pm->waterlevel == 0 ) 
  1802.         {
  1803.             // on ground will only play sounds if running
  1804.             if ( footstep && !pm->noFootsteps ) 
  1805.             {
  1806.                 PM_FootstepForSurface();
  1807.             }
  1808.         } 
  1809.         else if ( pm->waterlevel == 1 ) 
  1810.         {
  1811.             // splashing
  1812.             PM_AddEvent( EV_WATER_FOOTSTEP );
  1813.         }
  1814.         else if ( pm->waterlevel == 2 ) 
  1815.         {
  1816.             // wading / swimming at surface
  1817.             PM_AddEvent( EV_SWIM );
  1818.         } 
  1819.         else if ( pm->waterlevel == 3 ) 
  1820.         {
  1821.             // no sound when completely underwater
  1822.         }
  1823.     }
  1824. }
  1825.  
  1826. /*
  1827. ==============
  1828. PM_WaterEvents
  1829.  
  1830. Generate sound events for entering and leaving water
  1831. ==============
  1832. */
  1833. static void PM_WaterEvents( void ) 
  1834. {
  1835.     if ( !pml.previous_waterlevel && pm->waterlevel == 1 )
  1836.     {
  1837.         PM_AddEvent( EV_WATER_TOUCH );
  1838.     }
  1839.     else if ( pml.previous_waterlevel <= 1 && pm->waterlevel > 1 )
  1840.     {
  1841.         if ( pm->ps->velocity[2] < -100 )
  1842.         {
  1843.             PM_AddEvent( EV_WATER_LAND );
  1844.         }
  1845.     }
  1846.  
  1847.     //
  1848.     // check for head just coming out of water
  1849.     //
  1850.     if (pml.previous_waterlevel == 3 && pm->waterlevel != 3) {
  1851.         PM_AddEvent( EV_WATER_CLEAR );
  1852.     }
  1853. }
  1854.  
  1855. /*
  1856. ===============
  1857. PM_SetWeaponTime
  1858. ===============
  1859. */
  1860. static void PM_SetWeaponTime ( TAnimWeapon *aW )
  1861. {    
  1862.     TAnimInfoWeapon *aIW;
  1863.  
  1864.     if(!aW)
  1865.     {
  1866.         assert(0);
  1867.     }
  1868.  
  1869.     // Weapon model info tells us how long the anim is
  1870.     aIW = aW->mWeaponModelInfo;
  1871.     if ( !aIW )
  1872.     {
  1873.         return;
  1874.     }
  1875.  
  1876.     pm->ps->weaponTime = 1000.0f / aIW->mFPS[0] * aIW->mNumFrames[0] / aIW->mSpeed;
  1877.     pm->ps->weaponAnimTime = pm->ps->weaponTime;
  1878. }
  1879.  
  1880. /*
  1881. ===============
  1882. BG_GetWeaponNote
  1883. ===============
  1884. */
  1885. TNoteTrack *BG_GetWeaponNote( playerState_t* ps, int weapon, int anim, int animChoice, int callbackStep )
  1886. {
  1887.     TAnimWeapon        *aW;
  1888.     TAnimInfoWeapon *aIW;
  1889.     TNoteTrack        *note;
  1890.     int                n=0;
  1891.  
  1892.     note = NULL;
  1893.     aW=BG_GetInviewAnimFromIndex( weapon, anim&~ANIM_TOGGLEBIT);
  1894.     if (!aW)
  1895.     {
  1896.         return 0;
  1897.     }
  1898.  
  1899.     aIW = aW->mWeaponModelInfo;
  1900.     if ( !aIW )
  1901.     {
  1902.         return 0;
  1903.     }
  1904.  
  1905.     // Find the callback for the given step
  1906.     for ( note = aIW->mNoteTracks[ps->weaponAnimIdChoice], n=0; note && n < callbackStep; note = note->mNext, n++ )
  1907.     {
  1908.         // Do nothing, loop does it all
  1909.     }
  1910.  
  1911.     return(note);
  1912. }
  1913.  
  1914. /*
  1915. ==============
  1916. PM_CheckWeaponNotes
  1917. ==============
  1918. */
  1919. void PM_CheckWeaponNotes ( void )
  1920. {
  1921.     playerState_t    *ps;
  1922.     TAnimWeapon        *aW;
  1923.     TAnimInfoWeapon *aIW;
  1924.     TNoteTrack        *note;
  1925.     int                step;
  1926.     int                stepTime;
  1927.  
  1928.     pm->ps->weaponCallbackTime += pml.msec;    
  1929.  
  1930.     // 1st note step.
  1931.     step = 0;
  1932.     ps   = pm->ps;
  1933.     aW   = BG_GetInviewAnimFromIndex ( ps->weapon, (ps->weaponAnimId&~ANIM_TOGGLEBIT) );
  1934.  
  1935.     assert ( aW );
  1936.     if ( !aW )
  1937.     {
  1938.         return;
  1939.     }
  1940.  
  1941.     // Get the cached weapon model info
  1942.     aIW = aW->mWeaponModelInfo;
  1943.     if ( !aIW )
  1944.     {
  1945.         return;
  1946.     }
  1947.  
  1948.     stepTime = 1000.0f / aIW->mFPS[pm->ps->weaponAnimIdChoice] / aIW->mSpeed;;
  1949.     note     = aIW->mNoteTracks[pm->ps->weaponAnimIdChoice];
  1950.  
  1951.     while(note)
  1952.     {
  1953.         if( pm->ps->weaponCallbackTime >= note->mFrame * stepTime )
  1954.         {
  1955.             if(step > pm->ps->weaponCallbackStep)
  1956.             {            
  1957.                 if( !Q_stricmp("fire",note->mNote) || !Q_stricmp("altfire",note->mNote) )
  1958.                 {
  1959.                     if(pm->ps->weaponstate==WEAPON_FIRING)
  1960.                     {
  1961.                         int seed;
  1962.                         
  1963.                         // Update the seed
  1964.                         seed = pm->ps->stats[STAT_SEED];
  1965.                         Q_rand ( &seed );
  1966.                         seed = seed & 0xFFFF;
  1967.                         pm->ps->stats[STAT_SEED] = seed;
  1968.  
  1969.                         PM_AddEvent(EV_FIRE_WEAPON);
  1970.                         PM_Weapon_AddInaccuracy(ATTACK_NORMAL);
  1971.                         PM_Weapon_AddKickAngles(weaponData[pm->ps->weapon].attack[ATTACK_NORMAL].maxKickAngles);
  1972.  
  1973.  
  1974.                     }
  1975.                     else if(pm->ps->weaponstate==WEAPON_FIRING_ALT)
  1976.                     {
  1977.                         PM_AddEvent(EV_ALT_FIRE);
  1978.                         PM_Weapon_AddKickAngles(weaponData[pm->ps->weapon].attack[ATTACK_ALTERNATE].maxKickAngles);
  1979.                     }                            
  1980.                 }
  1981.  
  1982.                 PM_AddEventWithParm ( EV_WEAPON_CALLBACK, 
  1983.                                       ((step&0xFF) << 24) + 
  1984.                                       ((pm->ps->weaponAnimIdChoice&0xFF)<<16) + 
  1985.                                       (((ps->weaponAnimId&~ANIM_TOGGLEBIT)&0xFF)<<8) + 
  1986.                                       pm->ps->weapon);    
  1987.  
  1988.                 pm->ps->weaponCallbackStep=step;
  1989.             }
  1990.         }
  1991.  
  1992.         step++;                    
  1993.         note=note->mNext;
  1994.     }
  1995. }
  1996.  
  1997. /*
  1998. ===============
  1999. PM_SetWeaponAnimChoice
  2000. ===============
  2001. */
  2002. void PM_SetWeaponAnimChoice(TAnimWeapon *aW)
  2003. {
  2004.     TAnimInfoWeapon *aIW;
  2005.  
  2006.     if(!aW)
  2007.     {
  2008.         assert(0);
  2009.         return;
  2010.     }
  2011.     
  2012.     // Get the cached weapon model info
  2013.     aIW = aW->mWeaponModelInfo;
  2014.     if ( !aIW )
  2015.     {
  2016.         return;
  2017.     }
  2018.  
  2019.     pm->ps->weaponAnimIdChoice = rand()%aIW->mNumChoices;                
  2020. }
  2021.  
  2022. /*
  2023. ===============
  2024. PM_GetAnimFromName
  2025. ===============
  2026. */
  2027. TAnimWeapon* PM_GetAnimFromName ( char *animName, playerState_t *ps, int *animIndex )
  2028. {
  2029.     TAnimWeapon        *aW=0;
  2030.     TAnimInfoWeapon *aIW=0;
  2031.     char            tempname[MAX_QPATH];
  2032.  
  2033.     switch(ps->weapon)
  2034.     {
  2035.         case WP_KNIFE:
  2036.             if(!strcmp(animName,"charge"))
  2037.             {
  2038.                 // Get 'prefire' anim.
  2039.                 aW=BG_GetInviewAnim(pm->ps->weapon,"prefire",animIndex);
  2040.                 PM_SetWeaponAnimChoice(aW);
  2041.             }
  2042.             else if(!strcmp(animName,"fire"))
  2043.             {
  2044.                 aW=BG_GetInviewAnimFromIndex(ps->weapon,ps->weaponAnimId&~ANIM_TOGGLEBIT);
  2045.                 if((!strcmp(aW->mName,"prefire"))||strstr(aW->mName,"firetrans"))
  2046.                 {
  2047.                     // Get 'fire' anim.
  2048.                     aW=BG_GetInviewAnim(ps->weapon,"fire",animIndex);
  2049.                     PM_SetWeaponAnimChoice(aW);
  2050.                 }
  2051.                 else if(!strcmp(aW->mName,"fire"))
  2052.                 {
  2053.                     // Get 'firetrans' anim. We don't call PM_SetWeaponAnimChoice()
  2054.                     // because the firetrans anims are matched to the fire anims.
  2055.                     aIW=BG_GetInviewModelAnim(ps->weapon,"weaponmodel","fire");
  2056.                     strcpy(tempname,aIW->mTransition[ps->weaponAnimIdChoice]);
  2057.                     aW=BG_GetInviewAnim(ps->weapon,tempname,animIndex);
  2058.                 }
  2059.                 else
  2060.                 {
  2061.                     // Get 'prefire' anim.
  2062.                     aW=BG_GetInviewAnim(pm->ps->weapon,"fire",animIndex);
  2063.                     PM_SetWeaponAnimChoice(aW);
  2064.                 }
  2065.             }
  2066.             else if(!strcmp(animName,"fireend"))
  2067.             {
  2068.                 aW=BG_GetInviewAnim(ps->weapon,"fireend1",animIndex);
  2069.                 PM_SetWeaponAnimChoice(aW);
  2070.             }
  2071.             else
  2072.             {
  2073.                 // Nothing clever about the other sequences.
  2074.                 aW=BG_GetInviewAnim(pm->ps->weapon,animName,animIndex);
  2075.                 PM_SetWeaponAnimChoice(aW);
  2076.             }
  2077.             break;
  2078.  
  2079.         case WP_MM1_GRENADE_LAUNCHER:
  2080.         case WP_M590_SHOTGUN:
  2081.             if(!strcmp(animName,"reload"))
  2082.             {
  2083.                 aW=BG_GetInviewAnimFromIndex(ps->weapon,ps->weaponAnimId&~ANIM_TOGGLEBIT);
  2084.                 if(!strcmp(aW->mName,"reloadbegin")||!strcmp(aW->mName,"reloadshell"))
  2085.                 {
  2086.                     // Get 'reloadshell' anim.
  2087.                     aW=BG_GetInviewAnim(ps->weapon,"reloadshell",animIndex);
  2088.                 }
  2089.                 else
  2090.                 {
  2091.                     // Get 'reloadbegin' anim.
  2092.                     aW=BG_GetInviewAnim(pm->ps->weapon,"reloadbegin",animIndex);
  2093.                 }
  2094.             }
  2095.             else if(!strcmp(animName,"reloadend"))
  2096.             {
  2097.                 // Get 'reloadend' anim.
  2098.                 aW=BG_GetInviewAnim(ps->weapon,"reloadend",animIndex);
  2099.             }
  2100.             else
  2101.             {
  2102.                 // Nothing clever about the other sequences.
  2103.                 aW=BG_GetInviewAnim(pm->ps->weapon,animName,animIndex);
  2104.             }
  2105.             PM_SetWeaponAnimChoice(aW);
  2106.             break;
  2107.  
  2108.         case WP_M84_GRENADE:
  2109.         case WP_SMOHG92_GRENADE:
  2110.         case WP_ANM14_GRENADE:
  2111.         case WP_M15_GRENADE:
  2112.             if(!strcmp(animName,"charge"))
  2113.             {
  2114.                 // Get 'throwbegin' anim.
  2115.                 aW=BG_GetInviewAnim(ps->weapon,"throwbegin",animIndex);
  2116.             }
  2117.             else if(!strcmp(animName,"altcharge"))
  2118.             {
  2119.                 // Get 'throwbegin' anim.
  2120.                 aW=BG_GetInviewAnim(ps->weapon,"altthrowbegin",animIndex);
  2121.             }
  2122.             else if(!strcmp(animName,"fire"))
  2123.             {
  2124.                 // Get 'throwend' anim.
  2125.                 aW=BG_GetInviewAnim(ps->weapon,"throwend",animIndex);
  2126.             }
  2127.             else if(!strcmp(animName,"altfire"))
  2128.             {
  2129.                 // Get 'throwend' anim.
  2130.                 aW=BG_GetInviewAnim(ps->weapon,"altthrowend",animIndex);
  2131.             }
  2132.             else
  2133.             {
  2134.                 // Nothing clever about the other sequences.
  2135.                 aW=BG_GetInviewAnim(pm->ps->weapon,animName,animIndex);
  2136.             }
  2137.             PM_SetWeaponAnimChoice(aW);
  2138.             break;
  2139.  
  2140.         default:
  2141.             // Other weapons don't do anything fancy.
  2142.             aW=BG_GetInviewAnim(ps->weapon,animName,animIndex);
  2143.             PM_SetWeaponAnimChoice(aW);
  2144.             break;
  2145.     }
  2146.  
  2147.     return(aW);
  2148. }
  2149.  
  2150. /*
  2151. ===============
  2152. BG_GetWeaponAnim
  2153. ===============
  2154. */
  2155. TAnimWeapon *BG_GetWeaponAnim(int weaponAction,playerState_t *ps,int *animIndex)
  2156. {
  2157.     TAnimWeapon *aW=0;
  2158.  
  2159.     switch(weaponAction)
  2160.     {
  2161.         case WACT_READY:
  2162.             aW=PM_GetAnimFromName("ready",ps,animIndex);
  2163.             break;
  2164.         case WACT_IDLE:
  2165.             aW=PM_GetAnimFromName("idle",ps,animIndex);
  2166.             break;
  2167.         case WACT_FIRE:
  2168.             aW=PM_GetAnimFromName("fire",ps,animIndex);
  2169.             break;
  2170.         case WACT_FIRE_END:
  2171.             aW=PM_GetAnimFromName("fireend",ps,animIndex);
  2172.             break;
  2173.         case WACT_ALTFIRE:
  2174.             aW=PM_GetAnimFromName("altfire",ps,animIndex);
  2175.             break;
  2176.         case WACT_ALTFIRE_END:
  2177.             aW=PM_GetAnimFromName("altfireend",ps,animIndex);
  2178.             break;
  2179.         case WACT_RELOAD:
  2180.             aW=PM_GetAnimFromName("reload",ps,animIndex);
  2181.             break;
  2182.         case WACT_ALTRELOAD:
  2183.             aW=PM_GetAnimFromName("altreload",ps,animIndex);
  2184.             break;
  2185.         case WACT_RELOAD_END:
  2186.             aW=PM_GetAnimFromName("reloadend",ps,animIndex);
  2187.             break;
  2188.         case WACT_PUTAWAY:    
  2189.             aW=PM_GetAnimFromName("done",ps,animIndex);
  2190.             break;
  2191.         case WACT_ZOOMIN:
  2192.             aW=PM_GetAnimFromName("zoomin",ps,animIndex);
  2193.             break;
  2194.         case WACT_ZOOMOUT:    
  2195.             aW=PM_GetAnimFromName("zoomout",ps,animIndex);
  2196.             break;
  2197.         case WACT_CHARGE:
  2198.             aW=PM_GetAnimFromName("charge",ps,animIndex);
  2199.             break;
  2200.         case WACT_ALTCHARGE:
  2201.             aW=PM_GetAnimFromName("altcharge",ps,animIndex);
  2202.             break;
  2203.         default:
  2204.             Com_Printf("Anim unknown: %i\n",weaponAction);
  2205.             break;
  2206.     }
  2207.  
  2208.     return(aW);
  2209. }
  2210.  
  2211. /*
  2212. ===============
  2213. PM_HandleWeaponAction
  2214. ===============
  2215. */
  2216. static void PM_HandleWeaponAction(int weaponAction)
  2217. {
  2218.     TAnimWeapon *aW;
  2219.     int            animIndex;
  2220.  
  2221.     aW = BG_GetWeaponAnim ( weaponAction, pm->ps, &animIndex );
  2222.     if(!aW)
  2223.     {
  2224.         return;
  2225.     }
  2226.     
  2227.     // Reset callback timer. We have to account for any remaining weapontime
  2228.     // or we could miss off callbacks during sequences that are short in duration.
  2229.     pm->ps->weaponCallbackTime = -pm->ps->weaponTime;
  2230.     pm->ps->weaponCallbackStep = -1;
  2231.  
  2232.     PM_SetWeaponTime(aW);
  2233.     if((pm->ps->weaponAnimId&~ANIM_TOGGLEBIT)==animIndex)
  2234.     {
  2235.         animIndex=pm->ps->weaponAnimId^ANIM_TOGGLEBIT;
  2236.     }
  2237.  
  2238.     pm->ps->weaponAnimId = animIndex;
  2239. }
  2240.  
  2241. /*
  2242. ===============
  2243. PM_BeginZoomIn
  2244. ===============
  2245. */
  2246. static void PM_BeginZoomIn(void)
  2247. {
  2248.     // Reset the zom fov if not rezooming
  2249.     if ( !(pm->ps->pm_flags & PMF_ZOOM_REZOOM) )
  2250.     {
  2251.         pm->ps->zoomFov = 0;
  2252.     }
  2253.  
  2254.     pm->ps->weaponstate=WEAPON_ZOOMIN;
  2255.     PM_HandleWeaponAction(WACT_ZOOMIN);
  2256. }
  2257.  
  2258. /*
  2259. ===============
  2260. PM_BeginZoomOut
  2261. ===============
  2262. */
  2263. static void PM_BeginZoomOut(void)
  2264. {
  2265.     if ( !(pm->ps->pm_flags & PMF_ZOOMED) )
  2266.     {
  2267.         return;
  2268.     }
  2269.  
  2270.     if ( !(pm->ps->pm_flags & PMF_ZOOM_DEFER_RELOAD ) )
  2271.     {
  2272.         pm->ps->zoomFov = 0;
  2273.     }
  2274.  
  2275.     pm->ps->weaponstate=WEAPON_ZOOMOUT;
  2276.     PM_HandleWeaponAction(WACT_ZOOMOUT);
  2277.     pm->ps->zoomTime=pm->ps->commandTime;
  2278.     pm->ps->pm_flags &= ~(PMF_ZOOM_LOCKED|PMF_ZOOM_REZOOM|PMF_ZOOMED);
  2279. }
  2280.  
  2281.  
  2282. /*
  2283. ===============
  2284. PM_BeginWeaponChange
  2285. ===============
  2286. */
  2287. static void PM_BeginWeaponChange(int weapon)
  2288. {
  2289.     if ( weapon <= WP_NONE || weapon >= WP_NUM_WEAPONS )
  2290.     {
  2291.         return;
  2292.     }
  2293.  
  2294.     if ( !( pm->ps->stats[STAT_WEAPONS] & ( 1 << weapon ) ) )
  2295.     {
  2296.         return;
  2297.     }
  2298.     
  2299.     if ( pm->ps->weaponstate == WEAPON_DROPPING )
  2300.     {
  2301.         return;
  2302.     }
  2303.  
  2304.     // Dont allow switching to the weapon the client is already using
  2305.     if ( pm->ps->weapon == weapon )
  2306.     {
  2307.         PM_AddEvent(EV_CHANGE_WEAPON_CANCELLED );
  2308.  
  2309.         if ( pm->ps->weaponTime <= 0 )
  2310.         {
  2311.             // Add a little delay so it doenst fire because this was caused by
  2312.             // the menu selection
  2313.             pm->ps->weaponTime = 150;
  2314.         }
  2315.  
  2316.         return;
  2317.     }
  2318.  
  2319.     // turn off any kind of zooming when weapon switching.
  2320.     pm->ps->zoomFov      = 0;
  2321.     pm->ps->zoomTime  = 0;
  2322.     pm->ps->pm_flags &= ~(PMF_ZOOM_FLAGS);
  2323.  
  2324.     // Clear the weapon time
  2325.     pm->ps->weaponTime             = 0;
  2326.     pm->ps->weaponFireBurstCount = 0;
  2327.     pm->ps->weaponAnimTime         = 0;
  2328.  
  2329.     PM_AddEvent(EV_CHANGE_WEAPON);
  2330.     pm->ps->weaponstate = WEAPON_DROPPING;
  2331.  
  2332.     if( pm->ps->weapon >= WP_M84_GRENADE && pm->ps->weapon <= WP_M15_GRENADE && pm->ps->clip[ATTACK_NORMAL][pm->ps->weapon] <= 0 )
  2333.     {
  2334.         // We don't want to play the 'putaway' anim for the grenades if we are out of grenades!
  2335.         return;
  2336.     }
  2337.  
  2338.     PM_HandleWeaponAction(WACT_PUTAWAY);
  2339.  
  2340.     PM_StartTorsoAnim( pm->ps, weaponData[pm->ps->weapon].animDrop, pm->ps->weaponAnimTime );
  2341. }
  2342.  
  2343. /*
  2344. ===============
  2345. PM_FinishWeaponChange
  2346. ===============
  2347. */
  2348. static void PM_FinishWeaponChange( void )
  2349. {
  2350.     int    weapon;
  2351.  
  2352.     weapon = pm->cmd.weapon & ~WP_DELAYED_CHANGE_BIT;
  2353.  
  2354.     if( weapon < WP_NONE || weapon >= WP_NUM_WEAPONS )
  2355.     {
  2356.         weapon = WP_KNIFE;
  2357.     }
  2358.  
  2359.     if(!( pm->ps->stats[STAT_WEAPONS] & ( 1 << weapon ) ) )
  2360.     {
  2361.         weapon = WP_KNIFE;
  2362.     }
  2363.  
  2364.     PM_AddEvent(EV_READY_WEAPON);
  2365.     
  2366.     pm->ps->weapon            = weapon;
  2367.     pm->ps->weaponstate        = WEAPON_RAISING;
  2368.     pm->ps->weaponTime        = 0;
  2369.     pm->ps->weaponAnimTime    = 0;
  2370.  
  2371.     // Default to auto (or next available fire mode).
  2372.     if ( pm->ps->firemode[pm->ps->weapon] == WP_FIREMODE_NONE )
  2373.     {
  2374.         pm->ps->firemode[pm->ps->weapon] = BG_FindFireMode ( pm->ps->weapon, ATTACK_NORMAL, WP_FIREMODE_AUTO );
  2375.     }
  2376.  
  2377.     // We don't want to play the 'takeout' anim for the grenades if we are about to reload anyway
  2378.     if( pm->ps->weapon >= WP_M84_GRENADE && pm->ps->weapon <= WP_M15_GRENADE && pm->ps->clip[ATTACK_NORMAL][pm->ps->weapon] <=0 )
  2379.     {
  2380.         return;
  2381.     }
  2382.  
  2383.     PM_HandleWeaponAction(WACT_READY);
  2384.  
  2385.     pm->ps->weaponTime = min(500,pm->ps->weaponTime);
  2386.  
  2387.     PM_StartTorsoAnim( pm->ps, weaponData[pm->ps->weapon].animRaise, pm->ps->weaponAnimTime );
  2388. }
  2389.  
  2390. /*
  2391. ==============
  2392. PM_LoadShell
  2393.  
  2394. Only used for the M590 shotgun.
  2395. ==============
  2396. */
  2397. void PM_LoadShell(void)
  2398. {
  2399.     pm->ps->clip[ATTACK_NORMAL][pm->ps->weapon]++;
  2400.     pm->ps->ammo[weaponData[pm->ps->weapon].attack[ATTACK_NORMAL].ammoIndex]--;
  2401. }
  2402.  
  2403. /*
  2404. ==============
  2405. PM_StartRefillClip
  2406. ==============
  2407. */
  2408. void PM_StartRefillClip ( attackType_t attack )
  2409. {
  2410.     int    extra;
  2411.  
  2412.     assert ( attack >= ATTACK_NORMAL && attack < ATTACK_MAX );
  2413.  
  2414.     // Sniper rifle should unzoom first before reloading.
  2415.     if( pm->ps->pm_flags & PMF_ZOOMED )
  2416.     {
  2417.         pm->ps->pm_flags |= PMF_ZOOM_DEFER_RELOAD;
  2418.         PM_BeginZoomOut();
  2419.         return;
  2420.     }
  2421.  
  2422.     pm->ps->weaponstate=(attack==ATTACK_ALTERNATE)?WEAPON_RELOADING_ALT:WEAPON_RELOADING;
  2423.     pm->ps->weaponFireBurstCount=0;
  2424.  
  2425.     if(pm->ps->weapon!=WP_KNIFE)
  2426.     {
  2427.         // We don't want to play the reload anim for the knife, as it is part of
  2428.         // the throw anim anyway.
  2429.         if(attack==ATTACK_ALTERNATE)
  2430.         {
  2431.             PM_HandleWeaponAction(WACT_ALTRELOAD);
  2432.         }
  2433.         else
  2434.         {
  2435.             PM_HandleWeaponAction(WACT_RELOAD);
  2436.         }
  2437.     }
  2438.  
  2439.     if( pm->ps->weapon==WP_M590_SHOTGUN || pm->ps->weapon == WP_MM1_GRENADE_LAUNCHER )
  2440.     {
  2441.         PM_StartTorsoAnim ( pm->ps, weaponData[pm->ps->weapon].animReloadStart, pm->ps->weaponTime );
  2442.         return;
  2443.     }
  2444.     
  2445.     extra  = weaponData[pm->ps->weapon].attack[attack].clipSize;
  2446.     extra -= pm->ps->clip[attack][pm->ps->weapon];
  2447.  
  2448.     if(pm->ps->ammo[weaponData[pm->ps->weapon].attack[attack].ammoIndex]<extra)
  2449.     {
  2450.         extra=pm->ps->ammo[weaponData[pm->ps->weapon].attack[attack].ammoIndex];
  2451.     }
  2452.  
  2453.     pm->ps->clip[attack][pm->ps->weapon]+=extra;
  2454.     pm->ps->ammo[weaponData[pm->ps->weapon].attack[attack].ammoIndex]-=extra;
  2455.  
  2456.     // Rezoom the sniper rifle, if it was zoomed before we started reloading.
  2457.     if(pm->ps->pm_flags & PMF_ZOOM_DEFER_RELOAD )
  2458.     {
  2459.         pm->ps->pm_flags |= PMF_ZOOM_REZOOM;
  2460.         pm->ps->pm_flags &= ~PMF_ZOOM_DEFER_RELOAD;
  2461.     }
  2462.  
  2463.     PM_StartTorsoAnim ( pm->ps, weaponData[pm->ps->weapon].animReload, pm->ps->weaponTime );    
  2464. }
  2465.  
  2466. /*
  2467. ==============
  2468. PM_EndRefillClip
  2469. ==============
  2470. */
  2471. void PM_EndRefillClip(void)
  2472. {
  2473.     pm->ps->weaponstate=WEAPON_READY;
  2474.     pm->ps->weaponFireBurstCount = 0;
  2475. }
  2476.  
  2477. /*
  2478. ===============
  2479. PM_GetAttackButtons
  2480. ===============
  2481. */
  2482. int PM_GetAttackButtons(void)
  2483. {
  2484.     int buttons=pm->cmd.buttons;
  2485.  
  2486.     // Debounce firemode select button.
  2487.     if ( buttons & BUTTON_FIREMODE )
  2488.     {
  2489.         if(!(pm->ps->pm_debounce & PMD_FIREMODE))
  2490.         {
  2491.             pm->ps->pm_debounce |= PMD_FIREMODE;
  2492.         }
  2493.         else
  2494.         {
  2495.             buttons &= ~BUTTON_FIREMODE;
  2496.         }
  2497.     }
  2498.     else
  2499.     {
  2500.         pm->ps->pm_debounce &= ~PMD_FIREMODE;
  2501.     }
  2502.  
  2503.     // Handle firebutton in varous firemodes.
  2504.     switch( pm->ps->firemode[pm->ps->weapon] )
  2505.     {
  2506.         case WP_FIREMODE_AUTO:
  2507.             break;
  2508.  
  2509.         case WP_FIREMODE_BURST:
  2510.             // Debounce attack button and disable other buttons during burst fire.
  2511.             if(buttons&BUTTON_ATTACK)
  2512.             {
  2513.                 if( !(pm->ps->pm_debounce & PMD_ATTACK))
  2514.                 {
  2515.                     pm->ps->pm_debounce |= PMD_ATTACK;
  2516.                     if(!pm->ps->weaponFireBurstCount)
  2517.                     {
  2518.                         pm->ps->weaponFireBurstCount=3;
  2519.                     }
  2520.                 }
  2521.                 else
  2522.                 {
  2523.                     buttons &= ~BUTTON_ATTACK;
  2524.                 }
  2525.             }
  2526.             else
  2527.             {
  2528.                 pm->ps->pm_debounce &= ~PMD_ATTACK;
  2529.             }
  2530.             if(pm->ps->weaponFireBurstCount)
  2531.             {
  2532.                 buttons|=BUTTON_ATTACK;
  2533.                 buttons&=~BUTTON_ALT_ATTACK;
  2534.                 buttons&=~BUTTON_RELOAD;
  2535.                 buttons&=~BUTTON_ZOOMIN;
  2536.                 buttons&=~BUTTON_ZOOMOUT;
  2537.                 buttons&=~BUTTON_FIREMODE;
  2538.             }
  2539.             break;
  2540.  
  2541.         case WP_FIREMODE_SINGLE:
  2542.             // Debounce attack button.
  2543.             if(buttons&BUTTON_ATTACK)
  2544.             {
  2545.                 if(!(pm->ps->pm_debounce & PMD_ATTACK))
  2546.                 {
  2547.                     pm->ps->pm_debounce |= PMD_ATTACK;
  2548.                 }
  2549.                 else
  2550.                 {
  2551.                     buttons&=~BUTTON_ATTACK;
  2552.                 }
  2553.             }
  2554.             else
  2555.             {
  2556.                 pm->ps->pm_debounce &= ~PMD_ATTACK;
  2557.             }
  2558.  
  2559.             break;
  2560.     }
  2561.  
  2562.     // Handle single fire alt fire attacks or the sniper zoom
  2563.     if ( pm->ps->weapon == WP_MSG90A1 || (weaponData[pm->ps->weapon].attack[ATTACK_ALTERNATE].weaponFlags & (1<<WP_FIREMODE_SINGLE)) )
  2564.     {
  2565.         if ( buttons & BUTTON_ALT_ATTACK )
  2566.         {
  2567.             if( !(pm->ps->pm_debounce & PMD_ALTATTACK ) )
  2568.             {
  2569.                 pm->ps->pm_debounce |= PMD_ALTATTACK;
  2570.             }
  2571.             else
  2572.             {
  2573.                 buttons &= ~BUTTON_ALT_ATTACK;
  2574.             }
  2575.         }
  2576.         else
  2577.         {
  2578.             pm->ps->pm_debounce &= ~PMD_ALTATTACK;
  2579.         }                
  2580.     }
  2581.  
  2582.     return buttons;
  2583. }
  2584.  
  2585. /*
  2586. ==============
  2587. PM_Weapon_AddInaccuracy
  2588. ==============
  2589. */
  2590. #define ACCURACY_FADERATE    0.2
  2591. #define RECOVER_TIME        800
  2592. #define RECOVER_TIME_SQ        200000.0 
  2593.  
  2594. static void PM_Weapon_AddInaccuracy( attackType_t attack )
  2595. {
  2596.     assert ( attack >= ATTACK_NORMAL && attack < ATTACK_MAX );
  2597.  
  2598.     // Zoomed sniper weapons don't add innacuracy if ont hte ground
  2599.     if( (pm->ps->pm_flags & PMF_ZOOMED) && pml.groundPlane )
  2600.     {
  2601.         return;
  2602.     }
  2603.  
  2604.     pm->ps->inaccuracy += weaponData[pm->ps->weapon].attack[attack].inaccuracy;
  2605.  
  2606.     pm->ps->inaccuracyTime = RECOVER_TIME;
  2607.  
  2608.     if ( pm->ps->inaccuracy > weaponData[pm->ps->weapon].attack[attack].maxInaccuracy )
  2609.         pm->ps->inaccuracy = weaponData[pm->ps->weapon].attack[attack].maxInaccuracy;
  2610. }
  2611.  
  2612. /*
  2613. ==============
  2614. PM_Weapon_UpdateInaccuracy
  2615. ==============
  2616. */
  2617. static void PM_Weapon_UpdateInaccuracy(void)
  2618. {
  2619.     if( pm->ps->inaccuracy <= 0 )
  2620.     {
  2621.         pm->ps->inaccuracy = 0;
  2622.         return;
  2623.     }
  2624.  
  2625.     if ( pm->ps->weaponstate == WEAPON_FIRING || pm->ps->weaponstate == WEAPON_FIRING_ALT)
  2626.     {
  2627.         pm->ps->inaccuracyTime -= (pml.msec * 3 / 4);
  2628.     }
  2629.     else
  2630.     {
  2631.         pm->ps->inaccuracyTime -= pml.msec;
  2632.     }
  2633.  
  2634.     if ( pm->ps->inaccuracyTime <= 0 )
  2635.     {
  2636.         pm->ps->inaccuracy = 0;
  2637.     }
  2638.     else
  2639.     {
  2640.         //    decrement inaccuracy quadraticly to simulate the player recovering slowly at first, then rapidly
  2641.         int diff = RECOVER_TIME - pm->ps->inaccuracyTime;
  2642.  
  2643.         pm->ps->inaccuracy *= (1 - (diff*diff)/RECOVER_TIME_SQ);
  2644.     }
  2645. }
  2646.  
  2647. /*
  2648. ==============
  2649. PM_Weapon_AddKickAngles
  2650. ==============
  2651. */
  2652. static void PM_Weapon_AddKickAngles(vec3_t kickAngles)
  2653. {
  2654.     // Throw the new kick angles into the integer versions
  2655.     pm->ps->kickPitch += (int)(kickAngles[PITCH] * 500.0f);
  2656.  
  2657.     if ( pm->ps->kickPitch > 180000 )
  2658.         pm->ps->kickPitch = 180000;
  2659. }
  2660.  
  2661. /*
  2662. ==============
  2663. PM_Weapon_UpdateKickAngles
  2664. ==============
  2665. */
  2666. static void PM_Weapon_UpdateKickAngles(void)
  2667. {
  2668.     // bring our kickAngles back down to zero over time
  2669.     int            i;
  2670.     float        degreesCorrectedPerMSecond = 0.01f;
  2671.     qboolean    firing;
  2672.     float        degreesToCorrect = degreesCorrectedPerMSecond*pml.msec;
  2673.  
  2674.     vec3_t        kickAngles;
  2675.  
  2676.     // Extract the kick angles from their integer versions
  2677.     kickAngles[YAW]   = kickAngles[ROLL] = 0;
  2678.     kickAngles[PITCH] = (float)pm->ps->kickPitch / 1000.0f;
  2679.  
  2680.     firing = qfalse;
  2681.  
  2682.     // Determine if firing or not
  2683.     if ( pm->ps->weaponstate == WEAPON_FIRING || pm->ps->weaponstate == WEAPON_FIRING_ALT)
  2684.     {    
  2685.         firing = qtrue;
  2686.     }
  2687.  
  2688.     // If not firing then bring it down alot faster.
  2689.     if (!firing)
  2690.     {
  2691.         // return a whole lot faster if not firing
  2692.         VectorScale( kickAngles, 1.0f - (0.3f*((float)pml.msec/50.0f)), kickAngles );
  2693.  
  2694.         for (i = 0; i < 3; i++)
  2695.         {
  2696.             if (kickAngles[i] >= 0 && kickAngles[i] < 0.05f)
  2697.             {
  2698.                 kickAngles[i] = 0.0f;
  2699.             }
  2700.             else if (kickAngles[i] <= 0 && kickAngles[i] > -0.05f)
  2701.             {
  2702.                 kickAngles[i] = 0.0f;
  2703.             }
  2704.         }
  2705.     }
  2706.     else
  2707.     {
  2708.         for (i = 0; i < 3; i++)
  2709.         {
  2710.             if (kickAngles[i] > 0)
  2711.             {
  2712.                 if (kickAngles[i] < degreesToCorrect)
  2713.                 {
  2714.                     kickAngles[i] = 0;
  2715.                 }
  2716.                 else
  2717.                 {
  2718.                     kickAngles[i] -= degreesToCorrect;
  2719.                 }
  2720.             }
  2721.             else if (kickAngles[i] < 0)
  2722.             {
  2723.                 if (kickAngles[i] > -degreesToCorrect)
  2724.                 {
  2725.                     kickAngles[i] = 0;
  2726.                 }
  2727.                 else
  2728.                 {
  2729.                     kickAngles[i] += degreesToCorrect;
  2730.                 }
  2731.             }
  2732.         }
  2733.     }
  2734.  
  2735.     // Throw the new kick angles into the integer versions
  2736.     pm->ps->kickPitch = (int)(kickAngles[PITCH] * 1000.0f);
  2737. }
  2738.  
  2739. /*
  2740. ==============
  2741. PM_Goggles
  2742.  
  2743. Handles turning goggles on and off
  2744. ==============
  2745. */
  2746. static void PM_Goggles ( void )
  2747. {
  2748.     // ignore if not a normal player or dead or a ghost
  2749.     if ( pm->ps->pm_type != PM_NORMAL || pm->ps->stats[STAT_HEALTH] <= 0 || (pm->ps->pm_flags & PMF_GHOST) ) 
  2750.     {
  2751.         return;
  2752.     }
  2753.  
  2754.     // See if they even have goggles
  2755.     if ( pm->ps->stats[STAT_GOGGLES] == GOGGLES_NONE )
  2756.     {
  2757.         return;
  2758.     }
  2759.  
  2760.     // If the thermal goggles are on and the user has zoomed then turn them off
  2761.     if ( pm->ps->stats[STAT_GOGGLES] == GOGGLES_INFRARED )
  2762.     {
  2763.         // If the player is zoomed then no goggles
  2764.         if ( pm->ps->pm_flags & PMF_ZOOMED )
  2765.         {
  2766.             pm->ps->pm_flags &= ~PMF_GOGGLES_ON;
  2767.             return;
  2768.         }
  2769.     }
  2770.  
  2771.     // When goggles button isnt down there is nothing to do
  2772.     if ( !(pm->cmd.buttons & BUTTON_GOGGLES ) )
  2773.     {
  2774.         pm->ps->pm_debounce &= ~PMD_GOGGLES;
  2775.         return;
  2776.     }
  2777.  
  2778.     // Dont do anything if the goggles button is being held down
  2779.     if ( pm->ps->pm_debounce & PMD_GOGGLES )
  2780.     {
  2781.         return;
  2782.     }    
  2783.  
  2784.     // toggle the goggles
  2785.     pm->ps->pm_debounce |= PMD_GOGGLES;    
  2786.     pm->ps->pm_flags ^= PMF_GOGGLES_ON;
  2787.  
  2788.     // Play some noise
  2789.     PM_AddEventWithParm(EV_GOGGLES, (pm->ps->pm_flags&PMF_GOGGLES_ON) ? qtrue : qfalse );
  2790. }
  2791.  
  2792. /*
  2793. ==============
  2794. PM_WeaponIdle
  2795.  
  2796. Handles the progression of the looping idle animation
  2797. ==============
  2798. */
  2799. static void PM_WeaponIdle ( void )
  2800. {
  2801.     pm->ps->weaponAnimTime -= pml.msec;
  2802.     if ( pm->ps->weaponAnimTime <= 0 )
  2803.     {
  2804.         pm->ps->weaponAnimTime = 0;
  2805.         if ( pm->ps->weaponTime <= 0 )
  2806.         {
  2807.             PM_HandleWeaponAction(WACT_IDLE);
  2808.             pm->ps->weaponTime = 0;
  2809.         }
  2810.     }
  2811. }
  2812.  
  2813. /*
  2814. ==============
  2815. PM_Weapon
  2816.  
  2817. Generates weapon events and modifes the weapon counter
  2818. ==============
  2819. */
  2820. static void PM_Weapon( void )
  2821. {
  2822.     int                *ammoSource;
  2823.     int                attackButtons;
  2824.     attackData_t    *attackData;
  2825.     qboolean        altFire;
  2826.  
  2827.     // Get modifed attack buttons.
  2828.     attackButtons = PM_GetAttackButtons();
  2829.  
  2830.     // Gun goes away when using something
  2831.     if ( pm->ps->stats[STAT_USEWEAPONDROP] )
  2832.     {
  2833.         return;
  2834.     }
  2835.  
  2836.     // don't allow attack until all buttons are up
  2837.     if ( pm->ps->pm_flags & PMF_RESPAWNED ) 
  2838.     {
  2839.         return;
  2840.     }
  2841.  
  2842.     // ignore if not a normal player
  2843.     if ( pm->ps->pm_type != PM_NORMAL ) 
  2844.     {
  2845.         return;
  2846.     }
  2847.  
  2848.     // check for dead player
  2849.     if ( pm->ps->stats[STAT_HEALTH] <= 0 ) 
  2850.     {
  2851.         pm->ps->weapon = WP_NONE;
  2852.         return;
  2853.     }
  2854.  
  2855.     // Update the weapon inaccuracies and recoil
  2856.     PM_Weapon_UpdateInaccuracy();
  2857.     PM_Weapon_UpdateKickAngles();
  2858.  
  2859.     if( pm->ps->weaponTime > 0 )
  2860.     {
  2861.         pm->ps->weaponTime-=pml.msec;
  2862.     }
  2863.  
  2864.     // See if we've hit a note?
  2865.     PM_CheckWeaponNotes();
  2866.  
  2867.     // Check for weapon change.
  2868.     if( pm->ps->weaponstate == WEAPON_CHARGING || pm->ps->weaponstate == WEAPON_CHARGING_ALT )
  2869.     {
  2870.         // Can't change if weapon is charging.
  2871.         // Update the grenade timer
  2872.         if ( pm->ps->grenadeTimer > 0 )
  2873.         {
  2874.             pm->ps->grenadeTimer -= pml.msec;
  2875.  
  2876.             // Force it to go off if the timer has run out
  2877.             if ( pm->ps->grenadeTimer <= 0 )
  2878.             {
  2879.                 pm->ps->grenadeTimer = 1;
  2880.                 pm->ps->weaponTime = 0;
  2881.                 attackButtons &= ~(BUTTON_ATTACK|BUTTON_ALT_ATTACK);
  2882.             }
  2883.         }
  2884.     }
  2885.     else if ( pm->ps->weaponstate == WEAPON_SPAWNING )
  2886.     {
  2887.         if ( pm->cmd.weapon != pm->ps->weapon )
  2888.         {
  2889.             return;
  2890.         }
  2891.  
  2892.         pm->ps->weaponstate = WEAPON_READY;
  2893.         pm->ps->weaponTime = 0;
  2894.     }
  2895.     else if( pm->ps->weaponTime <= 0 || pm->ps->weaponstate < WEAPON_RELOADING )
  2896.     {
  2897.         // Dont change weapons if this is a weapon selection
  2898.         if ( (pm->cmd.weapon & WP_DELAYED_CHANGE_BIT) && ((pm->cmd.buttons&BUTTON_ATTACK)||(pm->cmd.buttons&BUTTON_ALT_ATTACK)) )
  2899.         {
  2900.             PM_BeginWeaponChange( pm->cmd.weapon & ~WP_DELAYED_CHANGE_BIT );
  2901.         }
  2902.         else if ( !(pm->cmd.weapon & WP_DELAYED_CHANGE_BIT) && pm->ps->weapon != pm->cmd.weapon )
  2903.         {
  2904.             PM_BeginWeaponChange( pm->cmd.weapon );
  2905.         }
  2906.     }
  2907.  
  2908.     if ( pm->ps->weaponTime > 0 )
  2909.     {
  2910.         // Handle the weapons idle animation
  2911.         PM_WeaponIdle ( );
  2912.  
  2913.         return;
  2914.     }
  2915.  
  2916.     // Reload the alt clip immediately
  2917.     if( !pm->ps->clip[ATTACK_ALTERNATE][pm->ps->weapon] && pm->ps->ammo[weaponData[pm->ps->weapon].attack[ATTACK_ALTERNATE].ammoIndex] > 0) 
  2918.     {
  2919.         switch(weaponData[pm->ps->weapon].attack[ATTACK_ALTERNATE].fireFromClip)
  2920.         {
  2921.             case 2:
  2922.                 // Reload altclip.
  2923.                 PM_StartRefillClip( ATTACK_ALTERNATE );                    
  2924.                 return;
  2925.         }
  2926.     }
  2927.  
  2928.     // Select firemode.
  2929.     if( attackButtons & BUTTON_FIREMODE )
  2930.     {
  2931.         pm->ps->firemode[pm->ps->weapon] = BG_FindFireMode( pm->ps->weapon, ATTACK_NORMAL, pm->ps->firemode[pm->ps->weapon] + 1 );
  2932.     }
  2933.  
  2934.     // Decrement burst fire counter if running.
  2935.     if(pm->ps->weaponFireBurstCount)
  2936.     {
  2937.         pm->ps->weaponFireBurstCount--;
  2938.     }
  2939.  
  2940.     // change weapon if time
  2941.     if ( pm->ps->weaponstate == WEAPON_DROPPING )
  2942.     {
  2943.         PM_FinishWeaponChange();
  2944.         return;
  2945.     }
  2946.  
  2947.     // Zoom in animation complete... now set zoom parms.
  2948.     if( pm->ps->weaponstate == WEAPON_ZOOMIN )
  2949.     {
  2950.         // The zoomfov may still be remembered from a reload while zooming
  2951.         if ( !pm->ps->zoomFov )
  2952.         {
  2953.             pm->ps->zoomFov = 20;
  2954.         }
  2955.  
  2956.         pm->ps->pm_flags |= PMF_ZOOMED;
  2957.         pm->ps->pm_flags |= PMF_ZOOM_LOCKED;
  2958.         pm->ps->pm_flags &= ~PMF_ZOOM_REZOOM;
  2959.         pm->ps->weaponstate=WEAPON_READY;
  2960.         return;
  2961.     }
  2962.  
  2963.     if( pm->ps->weaponstate==WEAPON_CHARGING || pm->ps->weaponstate==WEAPON_CHARGING_ALT )
  2964.     {
  2965.         switch(pm->ps->weapon)
  2966.         {        
  2967.             case WP_M84_GRENADE:
  2968.             case WP_SMOHG92_GRENADE:
  2969.             case WP_ANM14_GRENADE:
  2970.             case WP_M15_GRENADE:
  2971.                 if(!(attackButtons&(BUTTON_ATTACK|BUTTON_ALT_ATTACK)) ) 
  2972.                 {
  2973.                     if(pm->ps->weaponstate==WEAPON_CHARGING)
  2974.                     {
  2975.                         if ( pm->ps->grenadeTimer <= 1 )
  2976.                         {
  2977.                             PM_AddEvent(EV_FIRE_WEAPON);
  2978.                             pm->ps->weaponstate=WEAPON_FIRING;
  2979.                             pm->ps->weaponTime = 250;
  2980.                         }
  2981.                         else
  2982.                         {
  2983.                             pm->ps->weaponstate=WEAPON_FIRING;
  2984.                             PM_HandleWeaponAction(WACT_FIRE);
  2985.                             PM_StartTorsoAnim( pm->ps, TORSO_ATTACK_GRENADE_END, pm->ps->weaponTime);
  2986.                         }
  2987.                     }
  2988.                     else
  2989.                     {
  2990.                         if ( pm->ps->grenadeTimer <= 1 )
  2991.                         {
  2992.                             PM_AddEvent(EV_ALT_FIRE);
  2993.                             pm->ps->weaponstate=WEAPON_FIRING;
  2994.                             pm->ps->weaponTime = 250;
  2995.                         }
  2996.                         else
  2997.                         {
  2998.                             pm->ps->weaponstate=WEAPON_FIRING_ALT;
  2999.                             PM_HandleWeaponAction(WACT_ALTFIRE);
  3000.                             PM_StartTorsoAnim( pm->ps, TORSO_ATTACK_GRENADE_END, pm->ps->weaponTime);
  3001.                         }
  3002.                     }
  3003.                     return;
  3004.                 }
  3005.                 else
  3006.                 {
  3007.                     return;
  3008.                 }
  3009.                 break;
  3010.  
  3011.             default:
  3012.                 break;
  3013.         }
  3014.     }
  3015.  
  3016.     // Special end of fire animation for some weapons. Knife currently the only one.
  3017.     if( pm->ps->weaponstate == WEAPON_FIRING )
  3018.     {
  3019.         switch(pm->ps->weapon)
  3020.         {
  3021.             case WP_KNIFE:
  3022.                 if(!(pm->cmd.buttons&BUTTON_ATTACK))
  3023.                 {
  3024.                     PM_HandleWeaponAction(WACT_FIRE_END);
  3025.                     pm->ps->weaponTime=0;
  3026.                     pm->ps->weaponstate=WEAPON_READY;
  3027.                     return;
  3028.                 }
  3029.             default:
  3030.                 break;
  3031.         }
  3032.     }
  3033.  
  3034.     // ************************************************************************
  3035.     // Special reload behavior for warious weapons.
  3036.     // ************************************************************************
  3037.     if((pm->ps->weaponstate==WEAPON_RELOADING)||(pm->ps->weaponstate==WEAPON_RELOADING_ALT))
  3038.     {
  3039.         switch(pm->ps->weapon)
  3040.         {
  3041.             case WP_MM1_GRENADE_LAUNCHER:
  3042.             case WP_M590_SHOTGUN:
  3043.                 // The M590 shotgun has a unique behavior in that when it is reloading,
  3044.                 // the reload can be interrupted by firing. This cancels the reload of
  3045.                 // course.
  3046.                 if(attackButtons&(BUTTON_ATTACK|BUTTON_ALT_ATTACK)&&(pm->ps->clip[ATTACK_NORMAL][pm->ps->weapon]>0))
  3047.                 {
  3048.                     // Allow normal fire operation and cancel reload. Note: in
  3049.                     // the interests of gameplay, I allow us to go right to the
  3050.                     // fire anim, although it doesn't look as smooth as going to
  3051.                     // reload end and then fire.
  3052.                     PM_HandleWeaponAction(WACT_RELOAD_END);                    
  3053.                     PM_EndRefillClip();
  3054.  
  3055.                     PM_StartTorsoAnim ( pm->ps, weaponData[pm->ps->weapon].animReloadEnd, pm->ps->weaponTime );    
  3056.  
  3057.                     return;
  3058.                 }
  3059.                 else if( ( pm->ps->clip[ATTACK_NORMAL][pm->ps->weapon] < weaponData[pm->ps->weapon].attack[ATTACK_NORMAL].clipSize) &&
  3060.                          ( pm->ps->ammo[weaponData[pm->ps->weapon].attack[ATTACK_NORMAL].ammoIndex]>0))
  3061.                 {
  3062.                     // Load 1 more shell.
  3063.                     pm->ps->clip[ATTACK_NORMAL][pm->ps->weapon]++;
  3064.                     pm->ps->ammo[weaponData[pm->ps->weapon].attack[ATTACK_NORMAL].ammoIndex]--;
  3065.                     PM_HandleWeaponAction(WACT_RELOAD);
  3066.  
  3067.                     PM_StartTorsoAnim ( pm->ps, weaponData[pm->ps->weapon].animReload, pm->ps->weaponTime );
  3068.                     return;
  3069.                 }
  3070.                 else
  3071.                 {
  3072.                     // Weapon fully loaded so play end reload sequence.
  3073.                     PM_HandleWeaponAction(WACT_RELOAD_END);
  3074.                     PM_EndRefillClip();
  3075.  
  3076.                     PM_StartTorsoAnim ( pm->ps, weaponData[pm->ps->weapon].animReloadEnd, pm->ps->weaponTime );    
  3077.  
  3078.                     return;
  3079.                 }
  3080.                 break;
  3081.  
  3082.             default:
  3083.                 PM_EndRefillClip();
  3084.                 return;
  3085.         }
  3086.     }
  3087.     else if(pm->ps->pm_flags & PMF_ZOOM_DEFER_RELOAD )
  3088.     {
  3089.         PM_StartRefillClip( ATTACK_NORMAL );
  3090.         return;
  3091.     }
  3092.     else if( pm->ps->weapon==WP_KNIFE || (pm->ps->weapon>=WP_RPG7_LAUNCHER && pm->ps->weapon<=WP_M15_GRENADE) )
  3093.     {
  3094.         if(pm->ps->clip[ATTACK_NORMAL][pm->ps->weapon]<1)
  3095.         {
  3096.             // Clip is now empty so see if we have enough ammo to reload this weapon?
  3097.             if (pm->ps->ammo[weaponData[pm->ps->weapon].attack[ATTACK_NORMAL].ammoIndex] > 0) 
  3098.             {
  3099.                 // Yes, so reload it.
  3100.                 PM_StartRefillClip( ATTACK_NORMAL );
  3101.                 return;
  3102.             }
  3103.             else
  3104.             {
  3105.                 if(pm->ps->weapon!=WP_RPG7_LAUNCHER)
  3106.                 {
  3107.                     // Clear grenade type from inventory.
  3108.                     pm->ps->stats[STAT_WEAPONS]&=~(1<<pm->ps->weapon); 
  3109.  
  3110.                     // Out of ammo so switch weapons.
  3111.                     PM_AddEventWithParm(EV_NOAMMO, pm->ps->weapon);
  3112.                     return;
  3113.                 }
  3114.             }
  3115.         }
  3116.     }
  3117.     
  3118.     // Handle zooming in/out for sniper rifle.
  3119.     if(pm->ps->weapon==WP_MSG90A1)
  3120.     {
  3121.         if( (attackButtons&BUTTON_ALT_ATTACK) || (pm->ps->pm_flags & PMF_ZOOM_REZOOM) )
  3122.         {
  3123.             if( pm->ps->pm_flags & PMF_ZOOMED )
  3124.             {
  3125.                 PM_BeginZoomOut();
  3126.             }
  3127.             else
  3128.             {
  3129.                 PM_BeginZoomIn();
  3130.             }            
  3131.             return;
  3132.         }
  3133.         else if( pm->ps->pm_flags & PMF_ZOOMED )
  3134.         {
  3135.             if(pm->cmd.buttons&BUTTON_ZOOMIN)
  3136.             {
  3137.                 pm->ps->zoomFov = pm->ps->zoomFov >> 1;
  3138.                 if ( pm->ps->zoomFov < 5)
  3139.                 {
  3140.                     pm->ps->zoomFov = 5;
  3141.                 }
  3142.                 pm->ps->weaponTime=175;
  3143.                 return;
  3144.             }
  3145.             else if(pm->cmd.buttons&BUTTON_ZOOMOUT)
  3146.             {
  3147.                 pm->ps->zoomFov = pm->ps->zoomFov << 1;
  3148.                 if(pm->ps->zoomFov > 20 )
  3149.                 {
  3150.                     pm->ps->zoomFov = 20;
  3151.                 }
  3152.                 pm->ps->weaponTime=175;
  3153.                 return;
  3154.             }
  3155.         }
  3156.     }
  3157.  
  3158.     // Reload weapon?
  3159.     if ( attackButtons & BUTTON_RELOAD ) 
  3160.     {
  3161.         if(pm->ps->clip[ATTACK_NORMAL][pm->ps->weapon] < weaponData[pm->ps->weapon].attack[ATTACK_NORMAL].clipSize)
  3162.         {
  3163.             // No, so see if we have enough ammo to reload this weapon?
  3164.             if (pm->ps->ammo[weaponData[pm->ps->weapon].attack[ATTACK_NORMAL].ammoIndex] > 0) 
  3165.             {
  3166.                 // Yes, so reload it.
  3167.                 PM_StartRefillClip( ATTACK_NORMAL );
  3168.                 return;
  3169.             }
  3170.         }
  3171.     }
  3172.  
  3173.     // Start weapon when either frozen or not shooting
  3174.     if( pm->ps->stats[STAT_FROZEN] || !(attackButtons&(BUTTON_ATTACK|BUTTON_ALT_ATTACK)) )
  3175.     {
  3176.         // Handle the weapons idle animation
  3177.         PM_WeaponIdle ( );
  3178.  
  3179.         pm->ps->weaponstate = WEAPON_READY;
  3180.         return;
  3181.     }
  3182.  
  3183.     // Determine whether to use the alternate or normal attack info    
  3184.     if ( attackButtons & BUTTON_ATTACK )
  3185.     {
  3186.         altFire    = qfalse;
  3187.         attackData = &weaponData[pm->ps->weapon].attack[ATTACK_NORMAL];
  3188.     }
  3189.     else 
  3190.     {
  3191.         altFire    = qtrue;
  3192.         attackData = &weaponData[pm->ps->weapon].attack[ATTACK_ALTERNATE];
  3193.  
  3194.         // Cant throw last knife
  3195.         if( pm->ps->weapon==WP_KNIFE && pm->ps->ammo[attackData->ammoIndex] < 1 )
  3196.         {
  3197.             return;
  3198.         }
  3199.     }
  3200.  
  3201.     // Ammo taken from pool, clip or altclip?
  3202.     switch(attackData->fireFromClip)
  3203.     {
  3204.         case 0:
  3205.             ammoSource = &pm->ps->ammo[attackData->ammoIndex];
  3206.             break;
  3207.  
  3208.         default:
  3209.         case 1:
  3210.             ammoSource = &pm->ps->clip[ATTACK_NORMAL][pm->ps->weapon];
  3211.             break;
  3212.  
  3213.         case 2:
  3214.             ammoSource = &pm->ps->clip[ATTACK_ALTERNATE][pm->ps->weapon];
  3215.             break;
  3216.     }
  3217.  
  3218.     // Is there enough ammo to fire?
  3219.     if ( (*ammoSource) - attackData->fireAmount < 0 )
  3220.     {
  3221.         // No, so reload if there is more ammo
  3222.         if( pm->ps->ammo[ attackData->ammoIndex ] > 0 ) 
  3223.         {
  3224.             // If auto reloading is enabled then reload the gun
  3225.             if ( pm->ps->pm_flags & PMF_AUTORELOAD )
  3226.             {
  3227.                 switch ( attackData->fireFromClip)
  3228.                 {
  3229.                     case 1:
  3230.                         // Reload clip.
  3231.                         PM_StartRefillClip( ATTACK_NORMAL );
  3232.                         return;
  3233.  
  3234.                     case 2:
  3235.                         // Reload altclip.
  3236.                         PM_StartRefillClip( ATTACK_ALTERNATE );                    
  3237.                         return;
  3238.                 }
  3239.             }
  3240.         }
  3241.         // Out of ammo, switch weapons if not an alt-attack
  3242.         else if ( !altFire )
  3243.         {
  3244.             PM_AddEventWithParm (EV_NOAMMO, pm->ps->weapon);
  3245.         }
  3246.  
  3247.         // Handle the weapons idle animation
  3248.         PM_WeaponIdle ( );
  3249.  
  3250.         pm->ps->weaponstate = WEAPON_READY;
  3251.  
  3252.         return;
  3253.     }
  3254.  
  3255.     // This attack doesnt exist
  3256.     if ( !attackData->damage )
  3257.     {
  3258.         // Handle the weapons idle animation
  3259.         PM_WeaponIdle ( );
  3260.  
  3261.         pm->ps->weaponstate = WEAPON_READY;
  3262.  
  3263.         return;
  3264.     }
  3265.  
  3266.     // Decrease the ammo
  3267.     (*ammoSource) -= attackData->fireAmount;
  3268.  
  3269.     // Handle charging cases
  3270.     switch(pm->ps->weapon)
  3271.     {
  3272.         case WP_KNIFE:
  3273.             
  3274.             if ( altFire )
  3275.             {
  3276.                 if( pm->ps->weaponstate != WEAPON_FIRING && pm->ps->weaponstate != WEAPON_FIRING_ALT )
  3277.                 {
  3278.                     PM_HandleWeaponAction(WACT_ALTFIRE);
  3279.                     pm->ps->weaponstate=WEAPON_FIRING_ALT;
  3280.                 }
  3281.             }
  3282.             else
  3283.             {
  3284.                 PM_HandleWeaponAction ( WACT_FIRE );
  3285.                 pm->ps->weaponstate = WEAPON_FIRING;
  3286.             }
  3287.  
  3288.             // Play the torso animation associated with the attack
  3289.             PM_StartTorsoAnim ( pm->ps, attackData->animFire, pm->ps->weaponAnimTime );    
  3290.  
  3291.             break;
  3292.  
  3293.         case WP_M84_GRENADE:
  3294.         case WP_SMOHG92_GRENADE:
  3295.         case WP_ANM14_GRENADE:
  3296.         case WP_M15_GRENADE:
  3297.  
  3298.             // Start the detonation timer on the grenade going.
  3299.             pm->ps->grenadeTimer = attackData->projectileLifetime;
  3300.  
  3301.             if ( altFire )
  3302.             {
  3303.                 PM_HandleWeaponAction ( WACT_ALTCHARGE );
  3304.                 pm->ps->weaponstate = WEAPON_CHARGING_ALT;
  3305.             }
  3306.             else
  3307.             {
  3308.                 PM_HandleWeaponAction ( WACT_CHARGE );
  3309.                 pm->ps->weaponstate = WEAPON_CHARGING;
  3310.             }
  3311.  
  3312.             PM_StartTorsoAnim( pm->ps, TORSO_ATTACK_GRENADE_START, pm->ps->weaponTime);
  3313.  
  3314.             break;
  3315.  
  3316.         default:
  3317.  
  3318.             if ( altFire )
  3319.             {
  3320.                 PM_HandleWeaponAction(WACT_ALTFIRE);
  3321.                 pm->ps->weaponstate=WEAPON_FIRING_ALT;
  3322.             }
  3323.             else
  3324.             {
  3325.                 PM_HandleWeaponAction(WACT_FIRE);
  3326.                 pm->ps->weaponstate=WEAPON_FIRING;
  3327.             }
  3328.  
  3329.             pm->ps->weaponTime += attackData->fireDelay;
  3330.  
  3331.             // Play the torso animation associated with the attack
  3332.             if ( pm->ps->pm_flags & PMF_ZOOMED )
  3333.             {
  3334.                 PM_StartTorsoAnim ( pm->ps, attackData->animFireZoomed, pm->ps->weaponTime );    
  3335.             }
  3336.             else
  3337.             {
  3338.                 PM_StartTorsoAnim ( pm->ps, attackData->animFire, pm->ps->weaponTime );    
  3339.             }
  3340.  
  3341.             break;
  3342.     }
  3343. }
  3344.  
  3345. /*
  3346. ================
  3347. PM_DropTimers
  3348. ================
  3349. */
  3350. static void PM_DropTimers( void )
  3351.  {
  3352.     // drop misc timing counter
  3353.     if ( pm->ps->pm_time ) 
  3354.     {
  3355.         if ( pml.msec >= pm->ps->pm_time ) 
  3356.         {
  3357.             pm->ps->pm_flags &= ~PMF_ALL_TIMES;
  3358.             pm->ps->pm_time = 0;
  3359.         } 
  3360.         else 
  3361.         {
  3362.             pm->ps->pm_time -= pml.msec;
  3363.         }
  3364.     }
  3365. }
  3366.  
  3367. /*
  3368. ==============
  3369. PM_CheckLean
  3370. ==============
  3371. */
  3372. static void PM_CheckLean( void )
  3373. {
  3374.     trace_t        trace;
  3375.     qboolean    canlean;
  3376.     float        leanTime;
  3377.  
  3378.     if ( !pm || !pm->ps )
  3379.     {        
  3380.         return;
  3381.     }
  3382.     
  3383.     // No leaning as a spectator or a ghost
  3384.     if ( (pm->ps->pm_flags & PMF_GHOST) || pm->ps->pm_type == PM_SPECTATOR )
  3385.     {
  3386.         pm->ps->leanTime = LEAN_TIME;
  3387.         pm->ps->pm_flags &= ~PMF_LEANING;
  3388.         return;
  3389.     }
  3390.  
  3391.     leanTime = (float)pm->ps->leanTime - LEAN_TIME;
  3392.     canlean  = qfalse;
  3393.  
  3394.     // If their lean button is being pressed and they are on the ground then perform the lean
  3395.     if( (pm->cmd.buttons & (BUTTON_LEAN_RIGHT|BUTTON_LEAN_LEFT)) && (pm->ps->groundEntityNum != ENTITYNUM_NONE) )
  3396.     {
  3397.          vec3_t    start, end, right, mins, maxs;
  3398.         int        leanDir;
  3399.         
  3400.         if( pm->cmd.buttons & BUTTON_LEAN_RIGHT )
  3401.         {
  3402.             leanDir = 1;
  3403.         }
  3404.         else
  3405.         {
  3406.             leanDir = -1;
  3407.         }
  3408.  
  3409.         // check for collision
  3410.         VectorCopy( pm->ps->origin, start );
  3411.         start[2] += pm->ps->viewheight;
  3412.         AngleVectors( pm->ps->viewangles, NULL, right, NULL );
  3413.         VectorSet( mins, -6, -6, -8 ); 
  3414.         VectorSet( maxs, 6, 6, 8 ); 
  3415.         
  3416.         // since we're moving the camera over
  3417.         // check that move
  3418.         VectorMA( start, leanDir * LEAN_OFFSET * 1.25f, right, end );
  3419.         pm->trace(&trace, start, mins, maxs, end, pm->ps->clientNum, pm->tracemask );
  3420.  
  3421.         if ( trace.fraction < 0 || trace.fraction >= 1.0f )
  3422.         {
  3423.             leanTime += (leanDir * pml.msec);
  3424.             if( leanTime > LEAN_TIME )
  3425.             {
  3426.                 leanTime = LEAN_TIME;
  3427.             }
  3428.             else if( leanTime < -LEAN_TIME )
  3429.             {
  3430.                 leanTime = -LEAN_TIME;
  3431.             }
  3432.  
  3433.             canlean = qtrue;
  3434.         }
  3435.         else if ( (pm->ps->pm_flags&PMF_LEANING) && trace.fraction < 1.0f )
  3436.         {
  3437.             int templeanTime = (float)leanDir * (float)LEAN_TIME * trace.fraction;
  3438.  
  3439.             if ( fabs(templeanTime) < fabs(leanTime) )
  3440.             {
  3441.                 leanTime = templeanTime;
  3442.             }
  3443.         }
  3444.     }
  3445.  
  3446.     if ( !canlean )
  3447.     {
  3448.         if( leanTime > 0 )
  3449.         {
  3450.             leanTime -= pml.msec;
  3451.             if( leanTime < 0 )
  3452.             {
  3453.                 leanTime = 0;
  3454.             }
  3455.         }
  3456.         else if ( leanTime < 0 )
  3457.         {
  3458.             leanTime += pml.msec;
  3459.             if( leanTime > 0 )
  3460.             {
  3461.                 leanTime = 0;
  3462.             }
  3463.         }
  3464.     }    
  3465.  
  3466.     // Set a pm flag for leaning for convienience
  3467.     if ( leanTime != 0 )
  3468.     {
  3469.         pm->ps->pm_flags |= PMF_LEANING;
  3470.     }
  3471.     else
  3472.     {
  3473.         pm->ps->pm_flags &= ~PMF_LEANING;
  3474.     }
  3475.  
  3476.     // The lean time is kept positive by adding in the base lean time
  3477.     pm->ps->leanTime = (int) (leanTime + LEAN_TIME);
  3478. }
  3479.  
  3480. /*
  3481. ================
  3482. PM_UpdateViewAngles
  3483.  
  3484. This can be used as another entry point when only the viewangles
  3485. are being updated isntead of a full move
  3486. ================
  3487. */
  3488. void PM_UpdateViewAngles( playerState_t *ps, const usercmd_t *cmd ) 
  3489. {
  3490.     short    temp;
  3491.     int        i;
  3492.     vec3_t    kickAngles;
  3493.  
  3494.     if ( ps->pm_type == PM_INTERMISSION) 
  3495.     {
  3496.         return;        // no view changes at all
  3497.     }
  3498.  
  3499.     if ( ps->pm_type != PM_SPECTATOR && ps->stats[STAT_HEALTH] <= 0 ) 
  3500.     {
  3501.         return;        // no view changes at all
  3502.     }
  3503.  
  3504.     // Extract the kcik angles 
  3505.     kickAngles[PITCH] = ((float)ps->kickPitch / 1000.0f);
  3506.     kickAngles[YAW]   = kickAngles[ROLL] = 0;
  3507.  
  3508.     // circularly clamp the angles with deltas
  3509.     for (i=0 ; i<3 ; i++) 
  3510.     {
  3511.         temp = cmd->angles[i] + ps->delta_angles[i] - ANGLE2SHORT(kickAngles[i]);
  3512.         if ( i == PITCH ) 
  3513.         {
  3514.             // don't let the player look up or down more than 90 degrees
  3515.             if ( temp > 16000 ) 
  3516.             {
  3517.                 ps->delta_angles[i] = 16000 - (cmd->angles[i]- ANGLE2SHORT(kickAngles[i]));
  3518.                 temp = 16000;
  3519.             } 
  3520.             else if ( temp < -16000 ) 
  3521.             {
  3522.                 ps->delta_angles[i] = -16000 - (cmd->angles[i] - ANGLE2SHORT(kickAngles[i]));
  3523.                 temp = -16000;
  3524.             }
  3525.         }
  3526.         ps->viewangles[i] = SHORT2ANGLE(temp);
  3527.     }
  3528.  
  3529.     PM_CheckLean ( );
  3530. }
  3531.  
  3532. /*
  3533. ================
  3534. PM_AdjustAttackStates
  3535. ================
  3536. */
  3537.  
  3538. void PM_AdjustAttackStates( pmove_t *pm )
  3539. {
  3540.     int ammoOk;
  3541.  
  3542.     // Check ammo after usage...
  3543.     if(pm->cmd.buttons & BUTTON_ALT_ATTACK)
  3544.     {
  3545.         ammoOk = pm->ps->ammo[weaponData[pm->ps->weapon].attack[ATTACK_ALTERNATE].ammoIndex] - weaponData[pm->ps->weapon].attack[ATTACK_ALTERNATE].fireAmount;
  3546.     }
  3547.     else
  3548.     {
  3549.         ammoOk = pm->ps->clip[ATTACK_NORMAL][pm->ps->weapon ] - weaponData[pm->ps->weapon].attack[ATTACK_NORMAL].fireAmount;
  3550.     }
  3551.     
  3552.     // Set the firing flag.
  3553.     if(!(pm->ps->pm_flags & PMF_RESPAWNED) && (pm->ps->pm_type!=PM_INTERMISSION) && (ammoOk>=0))
  3554.     {
  3555.         if((pm->cmd.buttons & BUTTON_ALT_ATTACK)||(pm->ps->weaponstate==WEAPON_FIRING_ALT))
  3556.         {
  3557.             pm->ps->eFlags |= EF_ALT_FIRING;
  3558.         }
  3559.         else if((pm->cmd.buttons & BUTTON_ATTACK)||(pm->ps->weaponstate==WEAPON_FIRING))
  3560.         {
  3561.             pm->ps->eFlags &= ~EF_ALT_FIRING;
  3562.         }
  3563.  
  3564.         // This flag should always get set, even when alt-firing
  3565.         pm->ps->eFlags |= EF_FIRING;
  3566.     } 
  3567.     else 
  3568.     {
  3569.         // Clear 'em out
  3570.         pm->ps->eFlags &= ~(EF_FIRING|EF_ALT_FIRING);
  3571.     }
  3572. }
  3573.  
  3574. /*
  3575. ================
  3576. PmoveSingle
  3577. ================
  3578. */
  3579. void trap_SnapVector( float *v );
  3580.  
  3581. void PmoveSingle (pmove_t *pmove) {
  3582.     pm = pmove;
  3583.  
  3584.     // this counter lets us debug movement problems with a journal
  3585.     // by setting a conditional breakpoint fot the previous frame
  3586.     c_pmove++;
  3587.  
  3588.     // clear results
  3589.     pm->numtouch = 0;
  3590.     pm->watertype = 0;
  3591.     pm->waterlevel = 0;
  3592.  
  3593.     if ( pm->ps->stats[STAT_HEALTH] <= 0 ) {
  3594.         pm->tracemask &= ~CONTENTS_BODY;    // corpses can fly through bodies
  3595.     }
  3596.  
  3597.     // make sure walking button is clear if they are running, to avoid
  3598.     // proxy no-footsteps cheats
  3599.     if ( abs( pm->cmd.forwardmove ) > 64 || abs( pm->cmd.rightmove ) > 64 ) {
  3600.         pm->cmd.buttons &= ~BUTTON_WALKING;
  3601.     }
  3602.  
  3603.     // When the lean modifier button is held the strafe left and right keys
  3604.     // will act as lean left and right
  3605.     if ( pm->cmd.buttons & BUTTON_LEAN )
  3606.     {
  3607.         pm->cmd.buttons &= ~(BUTTON_LEAN_LEFT|BUTTON_LEAN_RIGHT);
  3608.  
  3609.         // Strafe left = lean left
  3610.         if ( pm->cmd.rightmove < 0 )
  3611.         {
  3612.             pm->cmd.buttons |= BUTTON_LEAN_LEFT;
  3613.         }
  3614.         // Strafe right = lean right
  3615.         else if ( pm->cmd.rightmove > 0 )
  3616.         {
  3617.             pm->cmd.buttons |= BUTTON_LEAN_RIGHT;
  3618.         }
  3619.  
  3620.         // NO strafing with lean button down
  3621.         pm->cmd.rightmove = 0;
  3622.     }
  3623.  
  3624.     // Cant move when leaning
  3625.     if ( (pm->cmd.buttons & (BUTTON_LEAN_LEFT|BUTTON_LEAN_RIGHT)))
  3626.     {
  3627. //        pm->cmd.rightmove = 0;
  3628.         pm->cmd.forwardmove = 0;
  3629.  
  3630.         // Cant jump when leaning
  3631.         if ( pm->cmd.upmove > 0 )
  3632.         {
  3633.             pm->cmd.upmove = 0;
  3634.         }
  3635.     }
  3636.     
  3637.     // Cant run when zoomed, leaning, or using something that takes time
  3638.     if ( (pm->ps->pm_flags&PMF_ZOOMED) || 
  3639.          (pm->ps->weaponstate == WEAPON_ZOOMIN) || 
  3640.          (pm->cmd.buttons & (BUTTON_LEAN_LEFT|BUTTON_LEAN_RIGHT)) || 
  3641.          (pm->ps->stats[STAT_USEWEAPONDROP]) )
  3642.     {
  3643.         if ( pm->cmd.forwardmove > 64 )
  3644.         {
  3645.             pm->cmd.forwardmove = 64;
  3646.         }
  3647.         else if ( pm->cmd.forwardmove < -64 )
  3648.         {
  3649.             pm->cmd.forwardmove = -64;
  3650.         }
  3651.  
  3652.  
  3653.         if ( pm->cmd.rightmove > 64 )
  3654.         {
  3655.             pm->cmd.rightmove = 64;
  3656.         }
  3657.         else if ( pm->cmd.rightmove < -64 )
  3658.         {
  3659.             pm->cmd.rightmove = -64;
  3660.         }
  3661.  
  3662.         pm->cmd.buttons |= BUTTON_WALKING;
  3663.     }
  3664.  
  3665.     // set the talk balloon flag
  3666.     if ( pm->cmd.buttons & BUTTON_TALK ) 
  3667.     {
  3668.         pm->ps->eFlags |= EF_TALK;
  3669.     } 
  3670.     else 
  3671.     {
  3672.         pm->ps->eFlags &= ~EF_TALK;
  3673.     }
  3674.  
  3675.     // In certain situations, we may want to control which attack buttons are pressed and what kind of functionality
  3676.     //    is attached to them
  3677.     PM_AdjustAttackStates( pm );
  3678.  
  3679.     // clear the respawned flag if attack and use are cleared
  3680.     if ( pm->ps->stats[STAT_HEALTH] > 0 && !( pm->cmd.buttons & BUTTON_ATTACK) )
  3681.     {
  3682.         pm->ps->pm_flags &= ~PMF_RESPAWNED;
  3683.     }
  3684.  
  3685.     // if talk button is down, dissallow all other input
  3686.     // this is to prevent any possible intercept proxy from
  3687.     // adding fake talk balloons
  3688.     if ( pmove->cmd.buttons & BUTTON_TALK ) 
  3689.     {
  3690.         // keep the talk button set tho for when the cmd.serverTime > 66 msec
  3691.         // and the same cmd is used multiple times in Pmove
  3692.         pmove->cmd.buttons = BUTTON_TALK;
  3693.         pmove->cmd.forwardmove = 0;
  3694.         pmove->cmd.rightmove = 0;
  3695.         pmove->cmd.upmove = 0;
  3696.     }
  3697.  
  3698.     // clear all pmove local vars
  3699.     memset (&pml, 0, sizeof(pml));
  3700.  
  3701.     // determine the time
  3702.     pml.msec = pmove->cmd.serverTime - pm->ps->commandTime;
  3703.     if ( pml.msec < 1 ) {
  3704.         pml.msec = 1;
  3705.     } else if ( pml.msec > 200 ) {
  3706.         pml.msec = 200;
  3707.     }
  3708.     pm->ps->commandTime = pmove->cmd.serverTime;
  3709.  
  3710.     // Frozen?
  3711.     if ( pm->ps->stats[STAT_FROZEN] )
  3712.     {
  3713.         pm->ps->stats[STAT_FROZEN] -= pml.msec;
  3714.         if ( pm->ps->stats[STAT_FROZEN] < 0 )
  3715.         {
  3716.             pm->ps->stats[STAT_FROZEN] = 0;
  3717.         }
  3718.         else
  3719.         {
  3720. //            pm->cmd.buttons = pm->cmd.buttons & (BUTTON_RELOAD|BUTTON_ATTACK|BUTTON_);    
  3721.             pm->cmd.forwardmove = 0;
  3722.             pm->cmd.rightmove = 0;
  3723.             pm->cmd.upmove = 0;
  3724.         }
  3725.     }
  3726.  
  3727.     // save old org in case we get stuck
  3728.     VectorCopy (pm->ps->origin, pml.previous_origin);
  3729.  
  3730.     // save old velocity for crashlanding
  3731.     VectorCopy (pm->ps->velocity, pml.previous_velocity);
  3732.  
  3733.     pml.frametime = pml.msec * 0.001;
  3734.  
  3735.     // update the viewangles
  3736.     PM_UpdateViewAngles( pm->ps, &pm->cmd );
  3737.  
  3738.     AngleVectors (pm->ps->viewangles, pml.forward, pml.right, pml.up);
  3739.  
  3740.     if ( pm->cmd.upmove < 10 ) 
  3741.     {
  3742.         // not holding jump
  3743.         pm->ps->pm_debounce &= ~PMD_JUMP;
  3744.     }
  3745.  
  3746.     // decide if backpedaling animations should be used
  3747.     if ( pm->cmd.forwardmove < 0 ) {
  3748.         pm->ps->pm_flags |= PMF_BACKWARDS_RUN;
  3749.     } else if ( pm->cmd.forwardmove > 0 || ( pm->cmd.forwardmove == 0 && pm->cmd.rightmove ) ) {
  3750.         pm->ps->pm_flags &= ~PMF_BACKWARDS_RUN;
  3751.     }
  3752.  
  3753.     if ( pm->ps->pm_type >= PM_DEAD ) {
  3754.         pm->cmd.forwardmove = 0;
  3755.         pm->cmd.rightmove = 0;
  3756.         pm->cmd.upmove = 0;
  3757.     }
  3758.  
  3759.     if ( pm->ps->pm_type == PM_SPECTATOR ) 
  3760.     {
  3761.         pm->mins[0] = -15;
  3762.         pm->mins[1] = -15;
  3763.         pm->maxs[0] = 15;
  3764.         pm->maxs[1] = 15;
  3765.         pm->mins[2] = MINS_Z;
  3766.         pm->maxs[2] = DEFAULT_PLAYER_Z_MAX;
  3767.         pm->ps->viewheight = DEFAULT_VIEWHEIGHT;
  3768.  
  3769. //        PM_FlyMove ();
  3770.         PM_NoclipMove ( );
  3771.         PM_DropTimers ();
  3772.         return;
  3773.     }
  3774.  
  3775.     if ( pm->ps->pm_type == PM_NOCLIP ) {
  3776.         PM_NoclipMove ();
  3777.         PM_DropTimers ();
  3778.         return;
  3779.     }
  3780.  
  3781.     if (pm->ps->pm_type == PM_FREEZE) {
  3782.         return;        // no movement at all
  3783.     }
  3784.  
  3785.     if ( pm->ps->pm_type == PM_INTERMISSION ) 
  3786.     {
  3787.         return;        // no movement at all
  3788.     }
  3789.  
  3790.     // set mins, maxs, and viewheight
  3791.     PM_CheckDuck ();
  3792.  
  3793.     // set groundentity
  3794.     PM_GroundTrace();
  3795.  
  3796.     // set watertype, and waterlevel
  3797.     PM_SetWaterLevel();
  3798.     pml.previous_waterlevel = pmove->waterlevel;
  3799.  
  3800.     PM_CheckCrouchJump ( );
  3801.  
  3802.     if ( pm->ps->pm_type == PM_DEAD ) {
  3803.         PM_DeadMove ();
  3804.     }
  3805.  
  3806.     PM_DropTimers();
  3807.  
  3808.     if ( pm->ps->pm_flags & PMF_LADDER )
  3809.     {
  3810.         PM_LadderMove ( );
  3811.     }
  3812.     else if (pm->ps->pm_flags & PMF_TIME_WATERJUMP) 
  3813.     {
  3814.         PM_WaterJumpMove();
  3815.     } 
  3816.     else if ( pm->waterlevel > 1 ) 
  3817.     {
  3818.         // swimming
  3819.         PM_WaterMove();
  3820.     } 
  3821.     else if ( pml.walking ) 
  3822.     {
  3823.         // walking on ground
  3824.         PM_WalkMove();
  3825.     } 
  3826.     else 
  3827.     {
  3828.         // airborne
  3829.         PM_AirMove();
  3830.     }
  3831.  
  3832.     // set groundentity, watertype, and waterlevel
  3833.     if(!(VectorCompare(pm->ps->origin,pml.previous_origin)))
  3834.     {
  3835.         // If we didn't move at all, then why bother doing this again -MW.
  3836.         PM_GroundTrace();
  3837.     }
  3838.  
  3839.     PM_SetWaterLevel();
  3840.  
  3841.     // turn goggles on/off
  3842.     PM_Goggles ( );
  3843.  
  3844.     // weapons
  3845.     PM_Weapon();
  3846.  
  3847.     // Use
  3848.     PM_Use ( );
  3849.  
  3850.     // torso animation
  3851.     PM_TorsoAnimation( pm->ps );
  3852.  
  3853.     // footstep events / legs animations
  3854.     PM_Footsteps();
  3855.  
  3856.     // entering / leaving water splashes
  3857.     PM_WaterEvents();
  3858.  
  3859.     // snap some parts of playerstate to save network bandwidth
  3860.     trap_SnapVector( pm->ps->velocity );
  3861. }
  3862.  
  3863. /*
  3864. ================
  3865. PM_UpdatePVSOrigin
  3866.  
  3867. The pvs of the client is calculated using its own origin and this function
  3868. ensures that the origin is set correctly.  The main reason for having a PVS
  3869. origin is that when leaning your can poke around corners which will in turn
  3870. change what you can see.
  3871. ================
  3872. */
  3873. void PM_UpdatePVSOrigin ( pmove_t *pmove )
  3874. {
  3875.     pm = pmove;
  3876.  
  3877.     // Set a pm flag for leaning and calculate the view origin for the lean
  3878.     if ( pm->ps->leanTime - LEAN_TIME != 0 )
  3879.     {
  3880.         vec3_t    right;
  3881.         float    leanOffset;
  3882.  
  3883.         leanOffset = (float)(pm->ps->leanTime - LEAN_TIME) / LEAN_TIME * LEAN_OFFSET;
  3884.  
  3885.         AngleVectors( pm->ps->viewangles, NULL, right, NULL );
  3886.         VectorMA( pm->ps->origin, leanOffset, right, pm->ps->pvsOrigin );
  3887.     }
  3888.     else
  3889.     {
  3890.         VectorCopy ( pm->ps->origin, pm->ps->pvsOrigin );
  3891.     }
  3892. }
  3893.  
  3894. /*
  3895. ================
  3896. Pmove
  3897.  
  3898. Can be called by either the server or the client
  3899. ================
  3900. */
  3901. void Pmove (pmove_t *pmove) {
  3902.     int            finalTime;
  3903.  
  3904.     finalTime = pmove->cmd.serverTime;
  3905.  
  3906.     if ( finalTime < pmove->ps->commandTime ) {
  3907.         return;    // should not happen
  3908.     }
  3909.  
  3910.     if ( finalTime > pmove->ps->commandTime + 1000 ) {
  3911.         pmove->ps->commandTime = finalTime - 1000;
  3912.     }
  3913.  
  3914.     pmove->ps->pmove_framecount = (pmove->ps->pmove_framecount+1) & ((1<<PS_PMOVEFRAMECOUNTBITS)-1);
  3915.  
  3916.     // chop the move up if it is too long, to prevent framerate
  3917.     // dependent behavior
  3918.     while ( pmove->ps->commandTime != finalTime ) {
  3919.         int        msec;
  3920.  
  3921.         msec = finalTime - pmove->ps->commandTime;
  3922.  
  3923.         if ( pmove->pmove_fixed ) {
  3924.             if ( msec > pmove->pmove_msec ) {
  3925.                 msec = pmove->pmove_msec;
  3926.             }
  3927.         }
  3928.         else {
  3929.             if ( msec > 66 ) {
  3930.                 msec = 66;
  3931.             }
  3932.         }
  3933.         pmove->cmd.serverTime = pmove->ps->commandTime + msec;
  3934.         PmoveSingle( pmove );
  3935.  
  3936.         PM_UpdatePVSOrigin ( pmove );    
  3937.  
  3938.         if ( pmove->ps->pm_debounce & PMD_JUMP ) 
  3939.         {
  3940.             pmove->cmd.upmove = 20;
  3941.         }
  3942.     }
  3943. }
  3944.  
  3945. /*
  3946. ================
  3947. BG_AddLadder
  3948.  
  3949. Adds a ladder to the ladder list
  3950. ================
  3951. */
  3952. void BG_AddLadder ( vec3_t absmin, vec3_t absmax, vec3_t fwd )
  3953. {
  3954.     pm_ladders[pm_laddercount].origin[0] = (absmax[0] + absmin[0]) / 2;
  3955.     pm_ladders[pm_laddercount].origin[1] = (absmax[1] + absmin[1]) / 2;
  3956.     pm_ladders[pm_laddercount].origin[2] = (absmax[2] + absmin[2]) / 2;
  3957.     VectorCopy ( fwd, pm_ladders[pm_laddercount].fwd );
  3958.     pm_laddercount++;
  3959. }
  3960.  
  3961. /*
  3962. ================
  3963. BG_FindLadder
  3964.  
  3965. Searches through the ladder list and finds the closes to the given origin
  3966. ================
  3967. */
  3968. int BG_FindLadder ( vec3_t pos )
  3969. {
  3970.     int        ladder;
  3971.     int        result;
  3972.     float    dist;
  3973.  
  3974.     dist   = 999999.0f;
  3975.     result = -1;
  3976.  
  3977.     for ( ladder = 0; ladder < pm_laddercount; ladder ++ )
  3978.     {
  3979.         float dist2 = DistanceSquared( pos, pm_ladders[ladder].origin );
  3980.  
  3981.         if ( dist2 < dist )
  3982.         {
  3983.             vec3_t diff;
  3984.             VectorSubtract ( pm_ladders[ladder].origin, pos, diff );
  3985.             diff[2] = 0;
  3986.  
  3987.             if ( VectorLengthSquared ( diff ) < 500 * 500 )
  3988.             {
  3989.                 dist = dist2;
  3990.                 result = ladder;
  3991.             }
  3992.         }
  3993.     }
  3994.  
  3995.     return result;
  3996. }
  3997.  
  3998.